Hi there! So, I’m working on building a basic Tkinter program that lets the user enter a password, and if it’s correct, it takes them to another page (or does something). The idea is that if the user enters a wrong password, a small error message saying “Incorrect Password” should appear and then disappear after 2 seconds. Sounds simple enough, right?
Well, it works perfectly the first time I enter a wrong password, the error message shows up, and after 2 seconds, it disappears just as expected. But then, if I enter the wrong password again, nothing happens. No error message, just a flood of errors that I can’t figure out.
I’ve included the code below, if any of you smart folks can spot what I’m doing wrong;
Error Code:
codefrom tkinter import *
import threading
master_pwd = "yoyodojo"
pwd_correct = False
root = Tk()
root.geometry("1080x720")
password_frame = Frame(root, bg="#D3D3D3", highlightbackground="black", highlightthickness=3)
password_frame.place(relwidth=0.4, relheight=0.25, relx=0.3, rely=0.325)
incorrect_label = Label(password_frame, text="Incorrect Password", font="Helvetica, 10", foreground="Red",
background="#D3D3D3")
def hide_incorrect_label():
incorrect_label.destroy()
def check_pwd(inputted_pwd):
if inputted_pwd == master_pwd:
global pwd_correct
pwd_correct = True
root.destroy()
else:
pwd_correct = False
password_input.delete(0, END)
incorrect_label.place(relx=0.33, rely=0.82)
x = threading.Timer(2.0, hide_incorrect_label)
x.start()
password_input = Entry(password_frame, relief=RIDGE, bg="#4f4f4f", fg="white", font="Helvetica, 14",
justify="center")
password_input.bind("<Return>", (lambda event: check_pwd(password_input.get())))
password_input.place(relwidth=0.8, relheight=0.2, relx=0.1, rely=0.6)
pwd_label = Label(password_frame, text="Enter Master Password:", font="Helvetica, 24", background="#D3D3D3")
pwd_label.pack(pady=20)
root.mainloop()
Here is the error I am getting:
codeException in Tkinter callback
Traceback (most recent call last):
File "C:\Users\benma\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\benma\Documents\Coding\File Hider\Code\Gui.py", line 37, in <lambda>
password_input.bind("<Return>", (lambda event: check_pwd(password_input.get())))
File "C:\Users\benma\Documents\Coding\File Hider\Code\Gui.py", line 30, in check_pwd
incorrect_label.place(relx=0.33, rely=0.82)
File "C:\Users\benma\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 2477, in place_configure
self.tk.call(_tkinter.TclError: bad window path name ".!frame.!label"
Here’s a correct and well-documented version of your code, along with an explanation of how it works:
Corrected Code:
codefrom tkinter import *
import threading
# Global variables
master_pwd = "yoyodojo" # The correct password
pwd_correct = False # Track whether the correct password was entered
# Create the main root window
root = Tk()
root.geometry("1080x720") # Set the size of the window
# Create a frame to hold the password input widgets
password_frame = Frame(root, bg="#D3D3D3", highlightbackground="black", highlightthickness=3)
password_frame.place(relwidth=0.4, relheight=0.25, relx=0.3, rely=0.325)
# Label to display incorrect password message (initially hidden)
incorrect_label = Label(password_frame, text="Incorrect Password", font=("Helvetica", 10),
foreground="Red", background="#D3D3D3")
def hide_incorrect_label():
"""
Hide the 'Incorrect Password' label after 2 seconds.
"""
incorrect_label.place_forget() # Use place_forget() instead of destroy() to hide
def check_pwd(inputted_pwd):
"""
Check if the inputted password matches the master password.
If it matches, close the root window. If not, show the error label.
"""
global pwd_correct
if inputted_pwd == master_pwd:
pwd_correct = True
root.destroy() # Close the window if the password is correct
else:
pwd_correct = False
password_input.delete(0, END) # Clear the input field
incorrect_label.place(relx=0.33, rely=0.82) # Show the incorrect password message
threading.Timer(2.0, hide_incorrect_label).start() # Hide the message after 2 seconds
# Create the password input field
password_input = Entry(password_frame, relief=RIDGE, bg="#4f4f4f", fg="white", font=("Helvetica", 14),
justify="center", show="*") # 'show="*"' masks the input
password_input.bind("<Return>", lambda event: check_pwd(password_input.get())) # Bind Enter key to password check
password_input.place(relwidth=0.8, relheight=0.2, relx=0.1, rely=0.6)
# Label prompting the user to enter the password
pwd_label = Label(password_frame, text="Enter Master Password:", font=("Helvetica", 24), background="#D3D3D3")
pwd_label.pack(pady=20)
# Run the GUI event loop
root.mainloop()
Explanation:
- Window Initialization:
- We create a Tkinter window (
root
) and set its size to 1080×720 pixels usinggeometry()
.
- We create a Tkinter window (
- Password Frame:
- A
Frame
is used to group the password input field and labels. This makes the UI more structured.
- A
- Label for Incorrect Password:
- We define a label (
incorrect_label
) to show an error message if the password is incorrect. Initially, this label is hidden.
- We define a label (
- Password Input and Binding:
- The
Entry
widget is used for the password input. We addshow="*"
to mask the input (commonly used for passwords). - We bind the Enter key event (
<Return>
) to the function that checks the password, so users can press Enter to submit.
- The
- Password Checking Function (
check_pwd
):- If the input matches
master_pwd
, we setpwd_correct
toTrue
and close the window usingroot.destroy()
. - If the password is incorrect, the input field is cleared, and the error label is shown for 2 seconds using
threading.Timer
.
- If the input matches
- Timer for Error Message:
threading.Timer
allows the error label to disappear after 2 seconds. Instead of destroying the label, we useplace_forget()
to hide it. This is more efficient than destroying and recreating it.
- Event Loop (
root.mainloop()
):- This starts the Tkinter event loop, keeping the GUI active and responsive to user inputs.
Final Thoughts:
This code provides a simple and functional password verification GUI using Tkinter. Here are some key improvements and recommendations:
- Error Handling: Instead of destroying the label every time, we use
place_forget()
to hide it, which is more efficient. - Input Masking: Adding
show="*"
to the password input field improves security by masking the entered text. - Threading: Using
threading.Timer
ensures that the GUI remains responsive while the error message is temporarily displayed. - Future Improvements:
- You could add functionality to limit the number of attempts.
- Implement more advanced security practices (like hashing passwords) if this were part of a real application.
This version ensures good user experience and code readability, while also being maintainable and easy to understand.