AttributeError:类型对象“ LoginApp”没有属性“ frames”

I'm trying to make a simple login GUI with tkinter but I keep getting this error :

AttributeError: type object 'LoginApp' has no attribute 'frames' 

This is the code for my LoginApp class :

class LoginApp(tkinter.Tk):
    def __init__(self, *args, **kwargs):
        tkinter.Tk.__init__(self, *args, **kwargs)

        container = tkinter.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 (StartPage, LogPage, RegPage):
            self.frame = F(container, self)
            self.frames[F] = self.frame
            self.frame.grid(row=0, column=0, sticky='nesw')

        self.showFrame(StartPage)

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

and this is my RegPage class:

class RegPage(tkinter.Frame):
    def __init__(self, parent, controller):
        tkinter.Frame.__init__(self, parent)

        self.userReg = tkinter.StringVar()
        self.pwdReg1 = tkinter.StringVar()
        self.pwdReg2 = tkinter.StringVar()

        label = tkinter.Label(self,text='Enter details below: ')
        label.pack(pady=10,padx=10)

        userLabel = tkinter.Label(self,text='Username * ')
        userLabel.pack()
        userEntry = tkinter.Entry(self,textvariable=self.userReg)
        userEntry.focus()
        userEntry.pack()

        pwd1Label = tkinter.Label(self,text='Password * ')
        pwd1Label.pack()
        pwdEntry1 = tkinter.Entry(self,textvariable=self.pwdReg1,show='*')
        pwdEntry1.pack()

        pwd2Label = tkinter.Label(self,text='Re-enter Password * ')
        pwd2Label.pack()
        pwdEntry2 = tkinter.Entry(self,textvariable=self.pwdReg2,show='*')
        pwdEntry2.pack()

        regButton = tkinter.Button(self,text='Register',width=5,height=1,command=lambda: self.regUser(LoginApp))
        regButton.pack(side='right')
        backButton = tkinter.Button(self,text='Back',width=5,height=1,command=lambda: controller.showFrame(StartPage))
        backButton.pack(side='left')

        self.resLabel = tkinter.Label(self,text='')
        self.resLabel.pack()

    def regUser(self, controller):
        user = self.userReg.get()
        pwd1 = self.pwdReg1.get()
        pwd2 = self.pwdReg2.get()

        logInfo = pickle.load(open('users.p','rb'))

        if user in logInfo:
            self.resLabel.config(text='User already exists',fg='red')
        else:
            if pwd1 == pwd2:
                logInfo.update( {user: pwd1} )
                pickle.dump(logInfo, open('users.p','wb'))
                self.resLabel.config(text='User registered',fg='green')
                controller.showFrame(controller, StartPage)

这是完整的错误消息:

   File "/usr/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
    return self.func(*args)
  File "/home/qumquat/coding/github/python/projects/self/login/gui/test.py", line 101, in <lambda>
    regButton = tkinter.Button(self,text='Register',width=5,height=1,command=lambda: self.regUser(LoginApp))
  File "/home/qumquat/coding/github/python/projects/self/login/gui/test.py", line 123, in regUser
    controller.showFrame(controller, StartPage)
  File "/home/qumquat/coding/github/python/projects/self/login/gui/test.py", line 27, in showFrame
    self.frame = self.frames[cont]
AttributeError: type object 'LoginApp' has no attribute 'frames'

I know it's that last line where I try and call showFrame that is wrong but I don't understand why because the function works perfectly with the back button.

抱歉,如果已经有这样的帖子,但我找不到任何帖子。

评论
  • Yes
    Yes 回复

    You didn't get what OOP is. You fell into a pithole. So, just to clarify: you have to understand, that LoginApp is a CLASS, a type of object, so you should really use controller = LoginApp() (note the parenthesis) and controller.showFrames(StartPage) (note: no controller as the first argument). This way, the controller is the object, so it essentially calls __init__ at creation and passes self to itself once you call showFrames, which is the method. Hope that's helpful!