使用Switch between two frames in tkinter中建议的方法,我试图在登录帧和寄存器帧之间切换。然而,在登录屏幕上按下注册按钮后调用showFrame(register)
时,会发生属性错误:
(frame=self.frames[pageName]; AttributeError:'loginScreen' object has no
attribute 'frames')
class mainActivity(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self,*args,**kwargs)
container=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 (loginScreen, register):
frame = F(container, self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="snew")
self.showFrame(loginScreen)
def showFrame(self, pageName):
frame=self.frames[pageName]
frame.tkraise()
#-------------------------------------------------
class loginScreen(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller=controller
self.regBtn =Button(self, text="Register", command=self.regBtnClicked)
self.regBtn.grid(row=2,column=1)
self.grid()
def regBtnClicked(self):
mainActivity.showFrame(self, register)
#send to register screen
#-------------------------------------------------
class register(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller=controller
self.grid(row=0, column=0)
self.cancelBtn = Button(self, text="Cancel",command=self.cancelBtnClicked)
self.cancelBtn.grid(row=4, column=1)
def cancelBtnClicked(self):
#return to login screen
mainActivity.showFrame(self, loginScreen)
app = mainActivity()
app.mainloop()
答案 0 :(得分:1)
您的代码存在一些问题。首先,你错过了for F in (loginScreen, register):
for循环的重要部分。
你需要:
page_name = F.__name__
这是用于为self.frames
字典的键部分提供字符串名称的代码行。
所以不要这样做:
self.frames[F]=frame
请改为:
self.frames[page_name] = frame
尝试在排除故障时使用print
语句。我只需要在发生错误之前添加print(self.frames)
,以便了解这里出了什么问题。
您还需要将self.showFrame(loginScreen)
更改为self.showFrame("loginScreen")
以及对showFrame()
的任何其他调用,以反映相同的更改。
你遇到的另一个问题是这一行:
mainActivity.showFrame(self, loginScreen)
您需要在此处引用控制器,如下所示:
self.controller.showFrame("loginScreen")
您的帧类中不需要self.grid(row=0, column=0)
,因为这些已经在for
循环中设置了。无需再做一次。
所有这些都可以看一下下面的代码:
from tkinter import *
class mainActivity(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container=Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames={}
for F in (loginScreen, register):
page_name = F.__name__
frame = F(container, self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="snew")
print(self.frames)
self.showFrame("loginScreen")
def showFrame(self, pageName):
frame=self.frames[pageName]
frame.tkraise()
#-------------------------------------------------
class loginScreen(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller=controller
self.regBtn = Button(self, text="Register", command=self.regBtnClicked)
self.regBtn.grid(row=2,column=1)
def regBtnClicked(self):
self.controller.showFrame("register")
#-------------------------------------------------
class register(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller=controller
self.cancelBtn = Button(self, text="Cancel",command=self.cancelBtnClicked)
self.cancelBtn.grid(row=4, column=1)
def cancelBtnClicked(self):
self.controller.showFrame("loginScreen")
app = mainActivity()
app.mainloop()