Home > database >  Why getting error : "home_frame is not defined" even if it's already global?
Why getting error : "home_frame is not defined" even if it's already global?

Time:12-30

I'm creating a simple Tkinter GUI app that has a simple login page. When user is logged in, home page is opened with three buttons: go to page A, go to page B or logout. But I get the error: line 75, in show_login_page home_frame.pack_forget() NameError: name 'home_frame' is not defined

Even if home_frame is declared global in line 33.

Here is my code:

import tkinter as tk

# Create the main window
window = tk.Tk()
window.title("Login")
window.geometry("300x300")

# Create the login page as a frame
login_frame = tk.Frame(window)

def check_login():
    # Get the username and password from the form
    username = username_entry.get()
    password = password_entry.get()

    # Check the login credentials
    if username == "1" and password == "1":
        # If the login is successful, destroy the login page and show the home page
        login_frame.pack_forget()
        show_home_page()
        print("Yo")
    else:
        # If the login is unsuccessful, show an error message
        error_label = tk.Label(login_frame, text="Invalid login. Please try again.")
        error_label.pack()

# Create the submit button
submit_button = tk.Button(login_frame, text="Submit", command=check_login)
submit_button.pack()

# Define the function to show the home page
def show_home_page():
    global home_frame
    # Create the home page as a frame
    home_frame = tk.Frame(window)
    home_frame.pack()
    try:
        page_a_frame.pack_forget()
        page_b_frame.pack_forget()
        login_frame.pack_forget()
    except NameError:
        pass

    # Create the buttons to navigate to the other pages
    logout_button = tk.Button(home_frame, text="Logout", command=show_login_page)
    page_a_button = tk.Button(home_frame, text="Page A", command=show_page_a)
    page_b_button = tk.Button(home_frame, text="Page B", command=show_page_b)
    logout_button.pack()
    page_a_button.pack()
    page_b_button.pack()

# Define the functions to show the other pages
def show_page_a():
    global page_a_frame
    home_frame.pack_forget()
    page_a_frame = tk.Frame(window)
    page_a_frame.pack()
    tk.Label(page_a_frame, text="This is page A").pack()
    back_button = tk.Button(page_a_frame, text="Back", command=show_home_page)
    back_button.pack()

def show_page_b():
    global page_b_frame
    home_frame.pack_forget()
    page_b_frame = tk.Frame(window)
    page_b_frame.pack()
    tk.Label(page_b_frame, text="This is page B").pack()
    back_button = tk.Button(page_b_frame, text="Back", command=show_home_page)
    back_button.pack()

# Define the function to show the login page
def show_login_page():
    global login_frame
    global home_frame
    home_frame.pack_forget()
    login_frame = tk.Frame(window)
    login_frame.pack()

    # Create the form for the user to enter their username and password
    username_label = tk.Label(login_frame, text="Username:")
    global username_entry
    username_entry = tk.Entry(login_frame, fg="blue")
    password_label = tk.Label(login_frame, text="Password:")
    global password_entry
    password_entry = tk.Entry(login_frame, show="*")

    # Place the form widgets on the login page
    username_label.pack()
    username_entry.pack()
    password_label.pack()
    password_entry.pack()

    # Create the submit button
    submit_button = tk.Button(login_frame, text="Submit", command=check_login)
    submit_button.pack()

# Show the login page
show_login_page()

# Run the main loop
window.mainloop()

CodePudding user response:

I never used tkinter before.

But adding the below line to top seems to be working.

home_frame = tk.Frame(window)

at line number 10.

EDIT: More info - my understanding

In my understanding, you are setting the home_frame variable in only show_home_page function.

But, you're calling home_frame.pack_forget, before show_home_page function is called.

so, home_frame is actually nothing.

just giving global variable will not assign it anything, see my test below

def foo(a):
    global c
    print(a)
    len(c)
    print(c)


>>> foo('adfa')
adfa
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in foo
NameError: name 'c' is not defined

if you assign something to c at the top, as we did in your case, it will consider that as something, and you will not get not defined error.

CodePudding user response:

If you notice carefully, you will see that you are calling the function show_login_page() first, and you are trying to use the variable home_frame from the global space which is not really declared already.

You are first decalring and assigning home_frame in the show_home_page() function, but that's been called after the show_login_page(), so there is no way for show_login_page() to know about home_frame.

So to fix this issue, you will have to declare and assign home_frame in the global space below the line where you assigned your login_frame variable.

So, the final code will be something like this:

import tkinter as tk

# Create the main window
window = tk.Tk()
window.title("Login")
window.geometry("300x300")

# Create the login page as a frame
login_frame = tk.Frame(window)
home_frame = tk.Frame(window)

def check_login():
    # Get the username and password from the form
    username = username_entry.get()
    password = password_entry.get()

    # Check the login credentials
    if username == "1" and password == "1":
        # If the login is successful, destroy the login page and show the home page
        login_frame.pack_forget()
        show_home_page()
        print("Yo")
    else:
        # If the login is unsuccessful, show an error message
        error_label = tk.Label(login_frame, text="Invalid login. Please try again.")
        error_label.pack()

# Create the submit button
submit_button = tk.Button(login_frame, text="Submit", command=check_login)
submit_button.pack()

# Define the function to show the home page
def show_home_page():
    # Create the home page as a frame
    home_frame.pack()
    try:
        page_a_frame.pack_forget()
        page_b_frame.pack_forget()
        login_frame.pack_forget()
    except NameError:
        pass

    # Create the buttons to navigate to the other pages
    logout_button = tk.Button(home_frame, text="Logout", command=show_login_page)
    page_a_button = tk.Button(home_frame, text="Page A", command=show_page_a)
    page_b_button = tk.Button(home_frame, text="Page B", command=show_page_b)
    logout_button.pack()
    page_a_button.pack()
    page_b_button.pack()

# Define the functions to show the other pages
def show_page_a():
    global page_a_frame
    home_frame.pack_forget()
    page_a_frame = tk.Frame(window)
    page_a_frame.pack()
    tk.Label(page_a_frame, text="This is page A").pack()
    back_button = tk.Button(page_a_frame, text="Back", command=show_home_page)
    back_button.pack()

def show_page_b():
    global page_b_frame
    home_frame.pack_forget()
    page_b_frame = tk.Frame(window)
    page_b_frame.pack()
    tk.Label(page_b_frame, text="This is page B").pack()
    back_button = tk.Button(page_b_frame, text="Back", command=show_home_page)
    back_button.pack()

# Define the function to show the login page
def show_login_page():
    global login_frame
    global home_frame
    home_frame.pack_forget()
    login_frame = tk.Frame(window)
    login_frame.pack()

    # Create the form for the user to enter their username and password
    username_label = tk.Label(login_frame, text="Username:")
    global username_entry
    username_entry = tk.Entry(login_frame, fg="blue")
    password_label = tk.Label(login_frame, text="Password:")
    global password_entry
    password_entry = tk.Entry(login_frame, show="*")

    # Place the form widgets on the login page
    username_label.pack()
    username_entry.pack()
    password_label.pack()
    password_entry.pack()

    # Create the submit button
    submit_button = tk.Button(login_frame, text="Submit", command=check_login)
    submit_button.pack()

# Show the login page
show_login_page()

# Run the main loop
window.mainloop()

I ran this program.. It works, but it still have some layout bugs which you have to look out for. Good luck fixing that :)

  • Related