问题描述
我正在使用此代码显示导航栏,该导航栏使我可以在当前显示的主页之间切换:
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
最后,使用此方法获取框架。由于controller
是App
的实例,因此您可以这样做:
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)