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 :)