I am trying to create a basic log in frame for my application (not worrying about it being complicated at all, it's for an A Level project). In the checklogin function, I am trying to retrieve the username input by the user, and seeing if it is in the database already, and will add a bit to check that the passwords match later. However I keep getting the error 'NameError: free variable 'userentry' referenced before assignment in enclosing scope'. Looking this error, it says the usual reason is because 'userentry' is being reassigned to later in the same function. However, I am struggling to see where this is the case. Any help will be appreciated.
class Login(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background="lightgreen")
def check_login():
sql = "SELECT Password FROM Player WHERE Username IN (?)"
parameters = (userentry.get())
cursor.execute(sql, parameters)
print(cursor.fetchall())
for col in range(5):
self.grid_columnconfigure(col, minsize=50)
for row in range(7):
self.grid_rowconfigure(row, minsize=60)
titlelbl = tk.Label(self,
text="Please enter your username and password",
font = "Verdana 20 bold",
fg="black",
bg="lightgreen")
titlelbl.grid(column=1,
row=0,
columnspan=3)
usernamelbl = tk.Label(self,
text="Username:",
font="Verdana 14",
bg="lightgreen")
usernamelbl.grid(column=1,
row=2)
passwordlbl = tk.Label(self,
text="Password:",
font="Verdana 14",
bg="lightgreen")
passwordlbl.grid(column=1,
row=4)
signupbtn = tk.Button(self,
text="Sign Up",
fg="lightgreen",
bg="darkgreen",
height="3",
width="12",
command = lambda: controller.show_frame("SignUp"))
signupbtn.grid(column=3,
row=6)
loginbtn = tk.Button(self,
text="Log In",
fg="lightgreen",
bg="darkgreen",
height="3",
width="12",
command = check_login())
loginbtn.grid(column=1,
row=6)
userentry = tk.Entry(self)
userentry.grid(column=3,
row=2)
passentry = tk.Entry(self,
show="*")
passentry.grid(column=3,
row=4)
In this code
loginbtn = tk.Button(self,
text="Log In",
fg="lightgreen",
bg="darkgreen",
height="3",
width="12",
command = check_login())
change command = check_login()
to command = check_login
(without the parentheses).
check_login
is the function object. check_login()
calls the function object and evaluates to the return value of the function.
The parentheses tell Python to call the function immediately. Here, when the tk.Button
is defined, the userentry
variable is not yet defined. This is why you are getting a NameError
when check_login
is called.
So if instead you use command = check_login
then the tk.Button
receives the function object, check_login
, which it can then call later, when the button is pressed.