pythonuser-interfacetkinter

How do I use tkraise on another frame class in Tkinter


I am currently learning to implement classes into my GUI. I know how to use tkraise normally however now its complicated.

I'm getting TypeError: login_page.widgets..sign_in() missing 1 required positional argument: 'self'

What I want the software to do is after I have logged in, to raise the 'Main frame'. I have hashed my attempt of using the tkraise in the sign_in function.

Could someone explain please.

from customtkinter import *

global d_text
d_text = ''

class software(CTk):
    def __init__(self):
        super().__init__()
        self.geometry('1000x800')

        
        Main = main(self)
        Login_page = login_page(self)
        Menu = menu(Main)
        Keypad = keypad(Main)
        Sub_menu = sub_menu(Main)
        Header = header(Main)
        Right_menu = right_menu(Main)
        Admin_menu = admin_menu(Main)
        self.mainloop()

class login_page(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=1000,height=800,fg_color='black')
        self.place(x=0,y=0)

        self.widgets()
    def widgets(self):
        
        def sign_in(self):
            if login_entryfield.get() == 'user123':
                if password_entryfield.get() == 'base12':
                    print('signed in as user')
                    #### self.Main.tkraise()
                else:
                    print('incorrect password')
                    
            else:
                print('incorrect user name')

        #widgets
        login_label = CTkLabel(self,text='Login',font = ("Arial", 20, "bold"))
        login_entryfield = CTkEntry(self, width=200)    
        password_label = CTkLabel(self,text='Password',font = ("Arial", 20, "bold"))
        password_entryfield = CTkEntry(self, width=200) 
        enter_button  = CTkButton(self,text='Login',font = ("Arial", 20, "bold"),command=sign_in)

        #layout
        login_label.place(x=300,y=100)
        login_entryfield.place(x=400,y=100)
        password_label.place(x=300,y=200)
        password_entryfield.place(x=400,y=200)
        enter_button.place(x=400,y=700)


class main(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent) 
        self.configure(width=1000,height=800, fg_color='black',corner_radius=0)
        self.place(x=0,y=0)

class header(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=1000,height=50, fg_color='green',corner_radius=0)
        self.place(x=0,y=0)

class menu(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=450,height=450,fg_color='red',corner_radius=0)
        self.place(x=0,y=50)

class right_menu(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(height=750,width=200, fg_color='purple',corner_radius=0)
        self.place(x=800,y=50)

        fv_button = CTkButton(self,text='Fruit&Veg',width=200,height=80)
        bakery_button = CTkButton(self,text='Bakery',width=200,height=80)
        Heavy_Misc_button = CTkButton(self,text='Heavy&Misc',width=200,height=80)
        bags_button = CTkButton(self,text='Recyclable Bags',width=200,height=80)
        downarrow_btn = CTkButton(self,text='↓',width=60,height=80)
        uparrow_btn = CTkButton(self,text='↑',width=60,height=80)

        fv_button.place(x=0,y=50)
        bakery_button.place(x=0,y=160)
        Heavy_Misc_button.place(x=0,y=270)
        bags_button.place(x=0,y=380)
        downarrow_btn.place(x=0,y=490)
        uparrow_btn.place(x=70,y=490)

class admin_menu(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=1000,height=150, fg_color='green',corner_radius=0)
        self.place(x=0,y=650)

        open_btn = CTkButton(self,text='^',width=50,height=50, corner_radius=0)
        open_btn.place(x=20,y=30)

        Lock_btn = CTkButton(self,text='Lock', width=125, height=75,corner_radius=0)
        Lock_btn.place(x=100,y=30)

        logoff_btn = CTkButton(self,text='Log Off', width=125, height=75,corner_radius=0)
        logoff_btn.place(x=250,y=30)

        report_btn = CTkButton(self,text='Report Abuse', width=125, height=75,corner_radius=0)
        report_btn.place(x=400,y=30)

        item_search_btn = CTkButton(self,text='Item Search', width=125, height=75,corner_radius=0)
        item_search_btn.place(x=550,y=30)

        Return_btn = CTkButton(self,text='Returns', width=125, height=75,corner_radius=0)
        Return_btn.place(x=700,y=30)

        Funds_management = CTkButton(self,text='Funds Management', width=125, height=75,corner_radius=0)
        Funds_management.place(x=850,y=30)
        



class keypad(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=300,height=450,fg_color='green', corner_radius=0)
        self.place(x=460,y=200)

        self.widget()   
    def widget(self):
        
        def display(var):
            global d_text
            d_text += str(var)
            lb1.configure(text=d_text)

        def clear():
            global d_text
            d_text = ''
            lb1.configure(text=d_text)
        
        def backspace():
            global d_text
            d_text = d_text[ :-1]
            lb1.configure(text=d_text)

        lb1 = CTkLabel(self,text='',width=300,fg_color='blue')

        btn1 = CTkButton(self, text=7,width=50,height=50,command=lambda:display(7))
        btn2 = CTkButton(self, text=8,width=50,height=50, command=lambda: display(8))
        btn3 = CTkButton(self, text=9,width=50,height=50, command=lambda: display(9))
        btn4 = CTkButton(self, text=4,width=50,height=50, command=lambda: display(4))
        btn5 = CTkButton(self, text=5,width=50,height=50, command=lambda: display(5))
        btn6 = CTkButton(self, text=6,width=50,height=50,command=lambda: display(6))
        btn7 = CTkButton(self, text=1,width=50,height=50, command=lambda: display(1))
        btn8 = CTkButton(self, text=2,width=50,height=50,command=lambda: display(2))
        btn9 = CTkButton(self, text=3,width=50,height=50,command=lambda: display(3))
        btn0 = CTkButton(self, text=0, width=50,height=50,command=lambda: display(0))
        decbtn = CTkButton(self,text='.',width=50,height=50,command=lambda: display('.'))
        clear_btn = CTkButton(self,text='C',width=50,height=50, command=lambda: clear())
        back_btn = CTkButton(self,text='<<',width=50,height=50, command=lambda: backspace())
        multiply_btn = CTkButton(self,text='X',width=50,height=50)
        ok_btn = CTkButton(self,text='OK',width=50,height=140)
        lb1.place(x=0,y=0)
        btn1.place(x=20,y=75)
        btn2.place(x=80,y=75)
        btn3.place(x=140,y=75)
        btn4.place(x=20,y=140)
        btn5.place(x=80,y=140)
        btn6.place(x=140,y=140)
        btn7.place(x=20,y=205)
        btn8.place(x=80,y=205)
        btn9.place(x=140,y=205)
        btn0.place(x=20,y=270)
        decbtn.place(x=80,y=270)
        clear_btn.place(x=140,y=270)
        back_btn.place(x=200,y=75)
        multiply_btn.place(x=200,y=140)
        ok_btn.place(x=200,y=205)

class sub_menu(CTkFrame):
    def __init__(self,parent):
        super().__init__(parent)
        self.configure(width=450,height=100,fg_color='yellow', corner_radius=0)
        self.place(x=0,y=450)

        self.widgets()
    def widgets(self):
        up_btn = CTkButton(self, text='↑', width=50,height=80)
        down_btn = CTkButton(self, text='↓', width=50, height=80)

        lb2 = CTkLabel(self, text='Balance due', font = ("Arial", 20, "bold"))
        lb3 = CTkLabel(self, text='0.00', font = ("Arial", 20, "bold"))
        lb4 = CTkLabel(self,text='0 items', font = ("Arial", 20, "bold"))

        up_btn.place(x=20,y=10)
        down_btn.place(x=80,y=10)
        lb2.place(x=150,y=60)
        lb3.place(x=300,y=60)
        lb4.place(x=150,y=0)

    
software()

Solution

  • The Problem

    The error you're encountering is because the sign_in function is defined inside the widgets method, making it a nested function. In this context, it does not automatically get self as its first parameter.

    To fix this, you need to move the sign_in function to be a method of the login_page class instead of being inside widgets.

    Additionally, to raise the main frame after a successful login, you need to pass a reference to the main frame instance to the login_page instance.

    Here’s a corrected version of your code:

    
    from customtkinter import *
    
    global d_text
    d_text = ''
    
    class software(CTk):
        def __init__(self):
            super().__init__()
            self.geometry('1000x800')
    
            self.Main = main(self)
            self.Login_page = login_page(self, self.Main)
            self.Menu = menu(self.Main)
            self.Keypad = keypad(self.Main)
            self.Sub_menu = sub_menu(self.Main)
            self.Header = header(self.Main)
            self.Right_menu = right_menu(self.Main)
            self.Admin_menu = admin_menu(self.Main)
            self.mainloop()
    
    class login_page(CTkFrame):
        def __init__(self, parent, main_frame):
            super().__init__(parent)
            self.main_frame = main_frame  # Store reference to the main frame
            self.configure(width=1000, height=800, fg_color='black')
            self.place(x=0, y=0)
    
            self.widgets()
    
        def sign_in(self):
            if self.login_entryfield.get() == 'user123':
                if self.password_entryfield.get() == 'base12':
                    print('signed in as user')
                    self.main_frame.tkraise()  # Raise the main frame
                else:
                    print('incorrect password')
            else:
                print('incorrect user name')
    
        def widgets(self):
            # widgets
            login_label = CTkLabel(self, text='Login', font=("Arial", 20, "bold"))
            self.login_entryfield = CTkEntry(self, width=200)
            password_label = CTkLabel(self, text='Password', font=("Arial", 20, "bold"))
            self.password_entryfield = CTkEntry(self, width=200, show='*')
            enter_button = CTkButton(self, text='Login', font=("Arial", 20, "bold"), command=self.sign_in)
    
            # layout
            login_label.place(x=300, y=100)
            self.login_entryfield.place(x=400, y=100)
            password_label.place(x=300, y=200)
            self.password_entryfield.place(x=400, y=200)
            enter_button.place(x=400, y=700)
    
    class main(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=1000, height=800, fg_color='black', corner_radius=0)
            self.place(x=0, y=0)
    
    class header(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=1000, height=50, fg_color='green', corner_radius=0)
            self.place(x=0, y=0)
    
    class menu(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=450, height=450, fg_color='red', corner_radius=0)
            self.place(x=0, y=50)
    
    class right_menu(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(height=750, width=200, fg_color='purple', corner_radius=0)
            self.place(x=800, y=50)
    
            fv_button = CTkButton(self, text='Fruit&Veg', width=200, height=80)
            bakery_button = CTkButton(self, text='Bakery', width=200, height=80)
            Heavy_Misc_button = CTkButton(self, text='Heavy&Misc', width=200, height=80)
            bags_button = CTkButton(self, text='Recyclable Bags', width=200, height=80)
            downarrow_btn = CTkButton(self, text='↓', width=60, height=80)
            uparrow_btn = CTkButton(self, text='↑', width=60, height=80)
    
            fv_button.place(x=0, y=50)
            bakery_button.place(x=0, y=160)
            Heavy_Misc_button.place(x=0, y=270)
            bags_button.place(x=0, y=380)
            downarrow_btn.place(x=0, y=490)
            uparrow_btn.place(x=70, y=490)
    
    class admin_menu(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=1000, height=150, fg_color='green', corner_radius=0)
            self.place(x=0, y=650)
    
            open_btn = CTkButton(self, text='^', width=50, height=50, corner_radius=0)
            open_btn.place(x=20, y=30)
    
            Lock_btn = CTkButton(self, text='Lock', width=125, height=75, corner_radius=0)
            Lock_btn.place(x=100, y=30)
    
            logoff_btn = CTkButton(self, text='Log Off', width=125, height=75, corner_radius=0)
            logoff_btn.place(x=250, y=30)
    
            report_btn = CTkButton(self, text='Report Abuse', width=125, height=75, corner_radius=0)
            report_btn.place(x=400, y=30)
    
            item_search_btn = CTkButton(self, text='Item Search', width=125, height=75, corner_radius=0)
            item_search_btn.place(x=550, y=30)
    
            Return_btn = CTkButton(self, text='Returns', width=125, height=75, corner_radius=0)
            Return_btn.place(x=700, y=30)
    
            Funds_management = CTkButton(self, text='Funds Management', width=125, height=75, corner_radius=0)
            Funds_management.place(x=850, y=30)
    
    class keypad(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=300, height=450, fg_color='green', corner_radius=0)
            self.place(x=460, y=200)
    
            self.widget()
    
        def widget(self):
            def display(var):
                global d_text
                d_text += str(var)
                lb1.configure(text=d_text)
    
            def clear():
                global d_text
                d_text = ''
                lb1.configure(text=d_text)
    
            def backspace():
                global d_text
                d_text = d_text[:-1]
                lb1.configure(text=d_text)
    
            lb1 = CTkLabel(self, text='', width=300, fg_color='blue')
    
            btn1 = CTkButton(self, text=7, width=50, height=50, command=lambda: display(7))
            btn2 = CTkButton(self, text=8, width=50, height=50, command=lambda: display(8))
            btn3 = CTkButton(self, text=9, width=50, height=50, command=lambda: display(9))
            btn4 = CTkButton(self, text=4, width=50, height=50, command=lambda: display(4))
            btn5 = CTkButton(self, text=5, width=50, height=50, command=lambda: display(5))
            btn6 = CTkButton(self, text=6, width=50, height=50, command=lambda: display(6))
            btn7 = CTkButton(self, text=1, width=50, height=50, command=lambda: display(1))
            btn8 = CTkButton(self, text=2, width=50, height=50, command=lambda: display(2))
            btn9 = CTkButton(self, text=3, width=50, height=50, command=lambda: display(3))
            btn0 = CTkButton(self, text=0, width=50, height=50, command=lambda: display(0))
            decbtn = CTkButton(self, text='.', width=50, height=50, command=lambda: display('.'))
            clear_btn = CTkButton(self, text='C', width=50, height=50, command=lambda: clear())
            back_btn = CTkButton(self, text='<<', width=50, height=50, command=lambda: backspace())
            multiply_btn = CTkButton(self, text='X', width=50, height=50)
            ok_btn = CTkButton(self, text='OK', width=50, height=140)
            lb1.place(x=0, y=0)
            btn1.place(x=20, y=75)
            btn2.place(x=80, y=75)
            btn3.place(x=140, y=75)
            btn4.place(x=20, y=140)
            btn5.place(x=80, y=140)
            btn6.place(x=140, y=140)
            btn7.place(x=20, y=205)
            btn8.place(x=80, y=205)
            btn9.place(x=140, y=205)
            btn0.place(x=20, y=270)
            decbtn.place(x=80, y=270)
            clear_btn.place(x=140, y=270)
            back_btn.place(x=200, y=75)
            multiply_btn.place(x=200, y=140)
            ok_btn.place(x=200, y=205)
    
    class sub_menu(CTkFrame):
        def __init__(self, parent):
            super().__init__(parent)
            self.configure(width=450, height=100, fg_color='yellow', corner_radius=0)
            self.place(x=0, y=450)
    
            self.widgets()
    
        def widgets(self):
            up_btn = CTkButton(self, text='↑', width=50, height=80)
            down_btn = CTkButton(self, text='↓', width=50, height=80)
    
            lb2 = CTkLabel(self, text='Balance due', font=("Arial", 20, "bold"))
            lb3 = CTkLabel(self, text='0.00', font=("Arial", 20, "bold"))
            lb4 = CTkLabel(self, text='0 items', font=("Arial", 20, "bold"))
    
            up_btn.place(x=20, y=10)
            down_btn.place(x=80, y=10)
            lb2.place(x=150, y=60)
            lb3.place(x=300, y=60)
            lb4.place(x=150, y=0)
    
    software()
    

    Some extra suggestions