从函数调用Tkinter框架控制器而非按钮命令

2 投票
2 回答
4636 浏览
提问于 2025-04-17 18:04

我有以下代码,它运行得很好:

import tkinter as tk

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (LoginPage, ProjPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, rowspan=12, columnspan=6, sticky="nsew")

        self.show_frame(LoginPage)

    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()

class LoginPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        Btn = tk.Button(self, text="Sign In", command=lambda: controller.show_frame(ProjPage))

但是我想把最后一个按钮的命令放到一个单独的函数里,这样我可以先做一些判断:

        Btn = tk.Button(self, text="Sign In", command=self.signIn)

    def signIn(self):
        # do some stuff here
        self.controller.show_frame(ProjPage)

可是这样不行;无论我尝试传递控制器,还是用一个lambda表达式,似乎都不管用。到底是哪里出了问题呢?

2 个回答

0

我的程序有一个主页面,上面有5个单选按钮和一个“确定”按钮,还有5个其他的页面。我希望在点击“确定”按钮后,根据选择的单选按钮,程序能跳转到相应的页面。

当点击“确定”按钮时,它会调用一个小函数,获取选中的单选按钮的值,然后根据这个值找到一个字符串(veg),这个字符串代表页面的名称。

以下是代码:

首先,我们导入需要的库:

import tkinter as tk
from tkinter import ttk
from win32print import StartPage

接下来,我们定义一个应用程序类 KBSapp,它是从 tkinter 的 Tk 类继承而来的:

class KBSapp(tk.Tk):
def init(self, *args, **kwargs):
tk.Tk.init(self, *args, **kwargs)
tk.Tk.iconbitmap(self,default="icon.ico")
tk.Tk.wm_title(self, "蔬菜作物的病虫害")
container = tk.Frame(self, width=200, height=200, bg='black')
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)

    self.frames = {}

    for F in (StartPage,carrot,celery, potato, wheat, bean):
        frame = F(container, self)
        self.frames[F] = frame
        frame.grid(row=0, column=0, sticky="nsew")

    self.show_frame(StartPage)

def show_frame(self, cont):
    frame = self.frames[cont]
    frame.tkraise( )

然后,我们定义一个 StartPage 类,它也是从 tk.Frame 继承的:

class StartPage(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)

    label = tk.Label(self, width=0, height=20)
    label.pack()

    button2 = ttk.Button(self, command=lambda : okclick(v) ,text='OK', width=25)
    button2.pack( )

    v = tk.IntVar( )
    self.option1 = ttk.Radiobutton(self,  text="Carrot", variable=v, value=1);self.option1.pack( )
    self.option2 = ttk.Radiobutton(self,  text="Celery", variable=v, value=2);self.option2.pack( )
    self.option3 = ttk.Radiobutton(self,  text="potato", variable=v, value=3);self.option3.pack( )
    self.option4 = ttk.Radiobutton(self,  text="wheat", variable=v, value=4);self.option4.pack( )
    self.option5 = ttk.Radiobutton(self,  text="bean", variable=v, value=5);self.option5.pack( )
    v.set(1)  # initializing the choice

接下来是处理“确定”按钮点击事件的函数 okclick(v):

def okclick(v):
global veg
input1=v.get( )
if input1==1:
veg="胡萝卜"
if input1==2:
veg='芹菜'
if input1==3:
veg='土豆'
if input1==4:
veg='小麦'
if input1==5:
veg='豆子'
print(veg)

然后我们定义了几个页面类,每个类代表一个不同的页面:

class carrot(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)
label = tk.Label(self, width=0, height=20)
label.pack( )
button3 = ttk.Button(self, command=lambda : controller.show_frame(celery) , text='芹菜', width=25)
button3.pack( )

class celery(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)
label = tk.Label(self, width=0, height=20)
label.pack( )
button4 = ttk.Button(self, command=lambda : controller.show_frame(potato) , text='土豆', width=25)
button4.pack( )

class potato(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)
label = tk.Label(self, width=0, height=20)
label.pack( )
button4 = ttk.Button(self, command=lambda : controller.show_frame(wheat) , text='小麦', width=25)
button4.pack( )

class wheat(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)
label = tk.Label(self, width=0, height=20)
label.pack( )
button4 = ttk.Button(self, command=lambda : controller.show_frame(bean) , text='豆子', width=25)
button4.pack( )

class bean(tk.Frame):
def init(self, parent, controller):
tk.Frame.init(self, parent)
label = tk.Label(self, width=0, height=20)
label.pack( )
button4 = ttk.Button(self, command=lambda : controller.show_frame(StartPage) , text='开始页面', width=25)
button4.pack( )

最后,我们创建应用程序的实例并运行它:

app = KBSapp( )
app.mainloop( )

7

你似乎没有在 self 中初始化 controller。可以在 LoginPage__init__ 方法里加上它,像这样:

self.controller = controller

撰写回答