【问题标题】:Switching frames with tkinter使用 tkinter 切换帧
【发布时间】:2020-07-07 12:28:36
【问题描述】:

我有以下应用程序,它由一个菜单栏和一个框架组成。按下按钮,框架的内容应该会改变。

到目前为止,这是我的代码:

import tkinter as tk


class ImageTool(tk.Tk):

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

        container = tk.Frame(self)
        container.grid(row=0,column=0,sticky="nsew")
        container.grid_rowconfigure(1, weight=1)
        container.grid_columnconfigure(2, weight=1)

        menu = SideMenu(container,self)
        menu.grid(row=0,column=0, sticky="nsew")


        self.frames = {}

        frame = StartPage(container, self)
        backuppage = BackupPage(container,self)


        self.frames[StartPage] = frame
        self.frames[BackupPage] = backuppage

        frame.grid(row=0, column=1, sticky="nsew")


        self.show_frame(StartPage)

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

        
class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        startpage_lbl = tk.Label(self, text="Start Page")
        startpage_lbl.pack(pady=10,padx=10,fill="both")
        
        self.winfo_toplevel().title("Image")

class BackupPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        self.winfo_toplevel().title(" Backup")
        
class SideMenu(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        self.btn_backup = tk.Button(self,text="BACKUP", command= controller.show_frame(BackupPage))
        self.btn_restore = tk.Button(self,text="RESTORE")

        self.btn_backup.pack(side = tk.TOP, fill= tk.X, expand = True )
        self.btn_restore.pack(side = tk.TOP, fill= tk.X, expand = True )


app = ImageTool()
app.mainloop()

我的问题如下: 当我尝试运行上面的代码时,我收到一个错误

AttributeError: '_tkinter.tkapp' object has no attribute 'frames'

但是,如果我没有完全弄错的话,我将 ImageTool 的实例作为控制器传递给 SideMenu 类,这就是对 controller.show_frame(BackupPage) 的命令调用在理论上应该起作用的原因。

我的错误是什么?

非常感谢您的任何帮助。

【问题讨论】:

  • 有趣的是,如果我将命令包装在 lambda 函数中,例如:self.btn_backup = tk.Button(self,text="BACKUP", command=lambda: controller.show_frame(BackupPage))应用程序运行但只在控制台中输出一个点而不是切换框架

标签: python python-3.x tkinter tk


【解决方案1】:

好的,我自己想出来的。 存在多个问题:

  1. 该命令必须包含在 lambda 表达式中,如下所示:
    self.btn_backup = tk.Button(self,text="BACKUP", command= lambda: controller.show_frame(BackupPage))
  2. 为了使show_frame() 方法中的frame.tkraise() 起作用,必须首先将框架加载到网格中:
frame.grid(row=0, column=1, sticky="nsew")
backuppage.grid(row=0, column=1, sticky="nsew")

【讨论】:

  • 作为一个选项,您可以使用functools.partial 来传递函数和参数而不调用它。 lambda 也可以,但在某些极端情况下可能会产生意想不到的结果。
  • @Axe319 哪些边缘情况会产生这种意想不到的结果?我的目标是构建一个尽可能健壮的应用程序,这对我来说是一个兴趣点。
  • 考虑一个例子,你有一个函数def foo(x): print(x)。然后用x = 'hello' 声明一个变量x。此时分配一个像bar = lambda: foo(x) 这样的lambda 并不一定意味着bar() 将打印'hello'。例如,如果之后你说x = 'world',那么bar() 现在将打印'world'
  • 这里是一些常见问题的好读物。 docs.python-guide.org/writing/gotchas 特别是关于后期绑定闭包的部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 2018-10-06
  • 2018-07-17
相关资源
最近更新 更多