Python 用于在tkinter中的两个帧之间切换的函数

Python 用于在tkinter中的两个帧之间切换的函数,python,python-3.x,tkinter,Python,Python 3.x,Tkinter,我正在查看的代码是,并且需要在他的类PageOnetk.Frame中增加一点功能。而不是像他那样使用下面的lambda命令: button1 = tk.Button(self, text="Back to Home", command=lambda: controller.show_frame(StartPage))` 我希望能够创建一个函数,其中包含if/then层次结构。。。特别是检查PageOne上的所有其他输入是否已首先完成,然后我知道如

我正在查看的代码是,并且需要在他的类PageOnetk.Frame中增加一点功能。而不是像他那样使用下面的lambda命令:

button1 = tk.Button(self, text="Back to Home",
                        command=lambda: controller.show_frame(StartPage))`
我希望能够创建一个函数,其中包含if/then层次结构。。。特别是检查PageOne上的所有其他输入是否已首先完成,然后我知道如何在允许帧更改之前完成

如果可以使用lambda单独完成此操作,则更好。有人能帮我吗

更新:根据Bryan的建议并对他链接的原始代码重新格式化,我现在有:

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "APP") #window heading
        self.title_font = tkfont.Font(family='Helvetica', size=12) #options: weight="bold",slant="italic"

        container = tk.Frame(self) #container = stack of frames; one on top is visible
        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, PageOne):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame #puts all pages in stacked order
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame("StartPage")

    def show_frame(self, page_name): #show a frame for the given page name
        frame = self.frames[page_name]
        frame.tkraise()

class StartPage(tk.Frame):

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

        label = tk.Label(self, text="This is the start page", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)

        button1 = tk.Button(self, text="Go to Page One",
                        command=lambda: controller.show_frame("PageOne"))
        button1.pack()
        button2.pack()

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

####FIX PART 1####
        self.next1 = tk.Button(self,text="Next",padx=18,highlightbackground="black", 
                           command=lambda: self.maybe_switch("PageTwo"))  
        self.next1.grid(row=10,column=1,sticky='E')

####FIX PART 2####
    def maybe_switch(self, page_name):
        if ###SOMETHING###:
            self.controller.show_frame(page_name)

if __name__ == "__main__":
    app = App()
    app.mainloop()

你不应该在lambda中加入任何逻辑。只需创建一个具有任何逻辑的普通函数,然后从按钮调用它。其实没那么复杂

class SomePage(...):
    def __init__(...):
        ...
        button1 = tk.Button(self, text="Back to Home", 
                        command=lambda: self.maybe_switch_page(StartPage))
        ...

    def maybe_switch_page(self, destination_page):
        if ...:
            self.controller.show_frame(destination_page)
        else:
            ...
如果您想要一个更通用的解决方案,请将逻辑移动到show_frame,并让它调用当前页面上的一个方法,以验证是否可以切换

例如:

    class Controller(...):
        ...
        def show_frame(self, destination):
            if self.current_page is None or self.current_page.ok_to_switch():
                # switch the page
            else:
                # don't switch the page

然后,只需在每个页面类中实现ok_to_切换

更好的方法是在FSM有限状态机中实现所有控制器逻辑,并且附加到命令事件的回调将自然成为FSM/控制器的事件。这将保证你的代码没有bug。所以,lambdas只会将事件发送给我在上面更新过的FSM(Nae),;Bryan在回复中的最后一次编辑修正了根据你的第一个建议,我得到:“PageOne”对象没有属性“controller”self.next1=tk.Buttonself,text=Next,command=self.maybe\u switch\u framePageTwo def maybe\u switch\u frameself,目标\帧:self.controller.show\帧目标_frame@evambivalence:然后您需要保存对控制器的引用。不幸的是,您选择的教程不是一个特别好的示例,并且忽略了这一点。这个教程是从这个网站上的一个答案的早期版本复制过来的,你可以在这里找到:@[Bryan Oakley]我已经在上面列出了我的全部代码;我感觉很接近,但还是不太接近。在我的想法中,我坚持在一个页面内使用你的功能example@evambivalence:stackoverflow不适用于扩展对话。如果您有新问题,请单击“提问”按钮。@[Bryan Oakley]非常感谢您的帮助。网站告诉我,今天我不能再问任何问题了。我会设法弄明白的。