从另一类的一个类访问变量的问题tkinter GUI-导航栏

问题描述

我正在使用此代码显示导航栏,该导航栏使我可以在当前显示的主页之间切换:

import tkinter as tk

class App(tk.Tk):
    def __init__(self,*args,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        self.geometry("600x400")
        container = tk.Frame(self)
        container.pack(side="top",fill="both",expand=True)
        container.grid_rowconfigure(0,weight=1)
        container.grid_columnconfigure(1,weight=1)

        self.mainframes = {}

        for F in (Mainframe1,Mainframe2):
            frame = F(container,self)
            frame.grid(row=0,column=1,sticky="nswe")
            self.mainframes[F] = frame

        navigationbar = NavigationbarFrame(container,self)
        navigationbar.grid(row=0,column=0,sticky="nswe")

        self.show_frame(Mainframe1)

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

class NavigationbarFrame(tk.Frame):
    def __init__(self,parent,controller):
        tk.Frame.__init__(self,bg="green")

        # self.mainframe1_self = app.mainframes[Mainframe1]
        # self.mainframe2_self = app.mainframes[Mainframe2]
        # tk.Button(self,text=self.mainframe1_self.pagename,command=lambda: controller.show_frame(Mainframe1)).grid(row=0,sticky="w",pady=5,padx=10)
        # tk.Button(self,text=self.mainframe2_self.pagename,command=lambda: controller.show_frame(Mainframe2)).grid(row=1,padx=10)

        tk.Button(self,text="Page 1",padx=10) #to be removed
        tk.Button(self,text="Page 2",padx=10) #to be removed

class Mainframe1(tk.Frame):
    def __init__(self,bg="yellow")
        tk.Label(self,text="this is Page 1",bg="yellow").grid(row=0,padx=20,pady=20)
        self.pagename = "Page 1"

class Mainframe2(tk.Frame):
    def __init__(self,bg="grey")
        tk.Label(self,text="this is Page 2",bg="grey").grid(row=0,pady=20)
        self.pagename = "Page 2"


app = App()
mainframe1_self = app.mainframes[Mainframe1]

print(app.mainframes)
print(mainframe1_self)
print(mainframe1_self.pagename)

app.mainloop()

现在,我正在尝试编辑NavigationbarFrame()类中的按钮。我想从类Mainframe1(),Mainframe2()访问按钮的文本[请参阅:#outcommented代码]

由于某种原因,我收到以下错误

Traceback (most recent call last):
  File "C:\Users\....py",line 53,in <module>
    app = App()
  File "C:\Users\....py",line 19,in __init__
    navigationbar = NavigationbarFrame(container,self)
  File "C:\Users\....py",line 32,in __init__
    self.mainframe1_self = app.mainframes[Mainframe1]
NameError: name 'app' is not defined

即使我创建了实例app = App()。
在app.mainloop()上方的打印命令中,我展示了如何从Mainframe1()类访问页面名称字符串。
我真的不知道为什么我不能从NavigationbarFrame()类访问它。您能帮我解决问题吗?

非常感谢!


编辑:
______________________________
按照Bryan Oakley的建议,我添加了get_frame()函数并编辑了NavigationbarFrame()类。一切工作正常!

由于我计划添加两个以上的按钮,因此现在尝试使用For循环创建它们:

class NavigationbarFrame(tk.Frame):
    def __init__(self,bg="green") #ersetzt {Frame(parent)}

        y=0
        for F in controller.mainframes:
            mainframe = controller.get_frame(F)
            tk.Button(self,text=mainframe.pagename,command = lambda: controller.show_frame(F)).grid(row=y,padx=10)
            y += 1

不幸的是,这使我想到了下一个问题:
我创建的两个按钮都以某种方式将我引导到Page2。我不明白其原因,因为第一个按钮应包括

command = lambda: controller.show_frame(Mainframe1)

,第二个按钮应包括

command = lambda: controller.show_frame(Mainframe2)

有人知道我的错误在哪里吗?

谢谢!

解决方法

在构造App时,app不存在。由于您使用的是面向对象的代码,因此您不应该依赖全局变量。最后,您的NavigationbarFrame不应尝试访问mainframes内部的App变量。即使它的编码方式是一个公共变量,其他类也确实不应该依赖于此-它会将页面与控制器紧密耦合。

相反,您应该在App中有一个方法可以为您返回给定的框架。然后,您可以使用该方法获取对其他框架的引用。

首先将get_page定义为与show_frame类似,但它不显示框架而是返回它:

class App(tk.Tk):
    ...

    def get_frame(self,cont):
        frame = self.mainframes[cont]
        return frame

最后,使用此方法获取框架。由于controllerApp的实例,因此您可以这样做:

class NavigationbarFrame(tk.Frame):
    def __init__(self,parent,controller):
        tk.Frame.__init__(self,bg="green")

        mainframe1 = controller.get_frame(Mainframe1)
        mainframe2 = controller.get_frame(Mainframe2)

        b1 = tk.Button(self,text=mainframe1.pagename,command=lambda: controller.show_frame(Mainframe1))
        b2 = tk.Button(self,text=mainframe.pagename,command=lambda: controller.show_frame(Mainframe2))

        b1.grid(row=0,column=0,sticky="w",pady=5,padx=10)
        b2.grid(row=1,padx=10)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...