2

I want to create a GUI in a class that can create pages using another class that creates frames and widgets. The pages are set using a class for them. I want to be able to GUI to be able to switch between the different set of pages. I can't create a button for the class of the Login_page that with switch the Login_page with the class of the Sign_page.

from tkinter import *
import random

class maingui:
    def __init__(self,title, geometry,):
        self.root = Tk()
        self.root.title(title)
        self.root.geometry(geometry)
        self.pageshow = Login_Page(self.root)
        self.root.mainloop()
    def changepage(self, page):
        self.page = page
        if self.page == 0:
            self.pageshow = Login_Page(self.root)
        if self.page == 1:
            self.pageshow = Sign_Page(self.root)
        self.root.mainloop()



class createWindow:
    def __init__(self,root, title, geometry,):
        self.root = root
        self.root.title(title)
        self.root.geometry(geometry)
        self.root.mainloop()
    
class createFrame:
    def __init__(self,window):
        self.window = window
        self.frame = Frame(self.window)
        self.frame.pack()
        print('c')
    def clear(self):
        pass
    def createlabel(self,message,postion = None):
        self.message =message
        self.postion = postion
        self.label= Label(self.frame, text =self.message)
        if self.postion == None:
            self.label.pack()
            print('a')
        else:
            print('b')
    def createbutton(self, text, command):
        self.text = text
        self.command = command
        self.button = Button(self.frame, text = self.text, command =self.command)

class Login_Page():
    def __init__(self,window):
        self.window = window
        self.frame = createFrame(self.window)
        self.frame.createlabel("Hello World")
        self.frame.createbutton("1",maingui.changepage(self.window,1))
class Sign_Page():
    def __init__(self,window):
        self.window = window
        self.frame = createFrame(self.window)
        self.frame.createlabel("Hello ")       

maingui = maingui("Rpg", "400x400") 

Edit: Exception has occurred: AttributeError '_tkinter.tkapp' object has no attribute 'root' On line

if self.page == 1:
      self.pageshow = Sign_Page(self.root)

On this line

self.frame.createbutton("1",maingui.changepage(self.window,1))

I try to create a button using a class and the command is from a different class.

4
  • I edit it to include the specific problem. Commented Dec 17, 2020 at 2:52
  • Suggest to make maingui inherit from Tk. Commented Dec 17, 2020 at 6:00
  • as for me you have too many mainloop() - found 3: in maingui.__init__(), in maingui.changepage(), in createWindow - but tkintner should use only one mainloop() Commented Dec 17, 2020 at 6:04
  • always put full erro message (starting at word "Tracebak") in question (not comment) as text (not screenshot). There are otheruseful information. Commented Dec 17, 2020 at 6:06

2 Answers 2

1

Since you pass self.root (instance of Tk()) of maingui class to Login_Page and assign it to self.window. Then self.window is used in maingui.changepage(self.window, 1) inside Login_Page class. Since you use class name to access changepage(), self.window will be treat as the self argument of changepage() and used in Sign_Page(self.root). That means you want to access the attribute root of self (instance of Tk()) but Tk does not have attribute root.

Suggest to make maingui interit from Tk instead of creating it inside __init__().

Below is an updated example based on yours:

from tkinter import *
#import random

class maingui(Tk):
    def __init__(self, title, geometry):
        super().__init__()
        self.title(title)
        self.geometry(geometry)
        self.pageshow = Login_Page(self)
    def changepage(self, page):
        self.page = page
        if self.page == 0:
            self.pageshow = Login_Page(self)
        if self.page == 1:
            self.pageshow = Sign_Page(self)

class createFrame:
    def __init__(self,window):
        self.window = window
        self.frame = Frame(self.window)
        self.frame.pack()
        print('c')
    def clear(self):
        pass
    def createlabel(self,message,postion = None):
        self.message =message
        self.postion = postion
        self.label= Label(self.frame, text =self.message)
        if self.postion == None:
            self.label.pack()
            print('a')
        else:
            print('b')
    def createbutton(self, text, command):
        self.text = text
        self.command = command
        self.button = Button(self.frame, text = self.text, command =self.command)
        self.button.pack() ###

class Login_Page():
    def __init__(self,window):
        self.window = window
        self.frame = createFrame(self.window)
        self.frame.createlabel("Hello World")
        ###self.frame.createbutton("1", maingui.changepage(self.window, 1)) ###
        self.frame.createbutton("1", lambda: self.window.changepage(1)) ###

class Sign_Page():
    def __init__(self,window):
        self.window = window
        self.frame = createFrame(self.window)
        self.frame.createlabel("Hello ")       

maingui = maingui("Rpg", "400x400") 
maingui.mainloop()
Sign up to request clarification or add additional context in comments.

Comments

1

Here is a working code, I would also suggest you read and practice classes before moving further.

(Note: I have not defined your clear method or added any new method, I have just corrected your existing code and rectified your error. you may further if you want, define your clear method and destroy your widgets).

from tkinter import *
import random

class maingui:
    def __init__(self, root, title, geometry):

        self.root = root
        self.root.title(title)
        self.root.geometry(geometry)
        self.pageshow = Login_Page(self, self.root)
      
    def changepage(self, page):
        self.page = page
        
        if self.page == 0:
            self.pageshow = Login_Page(self, self.root)

        if self.page == 1:
            self.pageshow = Sign_Page(self, self.root)

class createWindow:
    def __init__(self,root, title, geometry):
        self.root = root
        self.root.title(title)
        self.root.geometry(geometry)
      
class createFrame:
    def __init__(self, parent, window):
        self.window = window
        self.frame = Frame(self.window)
        self.frame.pack()
        self.label = Label(self.frame)
        self.button = Button(self.frame)
        self.parent = parent
        

    def clear(self):
        pass

    def createlabel(self,message,postion = None):
        self.message =message
        self.postion = postion
        self.label.config(text=self.message)
        
        if self.postion == None:
            self.label.pack()
        
        else:
           pass


    def createbutton(self, text='Login', cmd=0):
        self.text = text

        self.button.configure(text=self.text, command=lambda :self.parent.changepage(cmd))
        self.button.pack()

class Login_Page():
    def __init__(self, parent, window):
        self.window = window
        self.frame = createFrame(parent, self.window)
        self.frame.createlabel("Hello World bye")
        self.frame.createbutton("Welcome", 1)


class Sign_Page():
    def __init__(self, parent, window):
        self.window = window
        self.frame = createFrame(parent, self.window)
        self.frame.createlabel("Hello ")       


def main():
    root = Tk()
    maingui(root, "Rpg", "400x400")
    root.mainloop()
    
if __name__ =='__main__':
    main()

update: here is a way you can switch between pages(in my case you can switch between the sign-up and login page). click on login it will direct you to sign-up and vice-versa.

from tkinter import *
import random

class maingui:
    def __init__(self, root, title, geometry):

        self.root = root
        self.root.title(title)
        self.root.geometry(geometry)
        self.pageshow = Login_Page(self, self.root)
      
    def changepage(self, page):
        self.page = page
        
        if self.page == 0:
            #del self.pageshow
            self.pageshow = Login_Page(self, self.root)

        if self.page == 1:
            #del self.pageshow
            self.pageshow = Sign_Page(self, self.root)


class Login_Page:
    def __init__(self, parent, window):
        
        self.parent = parent
        
        self.frame = Frame(window)
        self.frame.pack()

        self.welcm_lbl = Label(self.frame, text='welcome')
        self.welcm_lbl.grid(row=0, column=1)

        self.name_lbl = Label(self.frame, text='name:')
        self.name_lbl.grid(row=1, column=0)

        self.name_entry = Entry(self.frame)
        self.name_entry.grid(row=1, column=1)

        self.sbt = Button(self.frame, text='login', command=self.clicked)
        self.sbt.grid(row=2, column=1)

    def clicked(self):
        self.frame.destroy()
        self.parent.changepage(1)
        

class Sign_Page():
    def __init__(self, parent, window):

        self.parent = parent
        
        self.frame = Frame(window)
        self.frame.pack()

        self.welcm_lbl = Label(self.frame, text='welcome sign-up')
        self.welcm_lbl.grid(row=0, column=1)

        self.name_lbl = Label(self.frame, text='name:')
        self.name_lbl.grid(row=1, column=0)

        self.name_entry = Entry(self.frame)
        self.name_entry.grid(row=1, column=1)

        self.sbt = Button(self.frame, text='sign-up', command=self.clicked)
        self.sbt.grid(row=2, column=1)      

    def clicked(self):
        self.frame.destroy()
        self.parent.changepage(0)
        
    
def main():
    root = Tk()
    maingui(root, "Rpg", "400x400")
    root.mainloop()
    
if __name__ =='__main__':
    main()

2 Comments

as for me you have too many mainloop() - found 3: in main(), in changepage(), in createWindow - but tkintner should use only one mainloop()
@furas yep, I forgot to remove them thx for pointing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.