Posts: 3
Threads: 1
Joined: Mar 2021
Mar-23-2021, 09:42 PM
(This post was last modified: Mar-23-2021, 09:45 PM by buran.)
Hi, I have trouble making get work if its called a from a button press...
def UserLogin2():
attempt_made = False
user_record = ['someblankerrortext']
global login_verified
global run_program
global logged_in_user_record
login_verified = False
run_program = True
logged_in_user_record = [0,"","",0]
while login_verified == False and run_program == True:
LoginWindow = tkinter.Tk()
LoginWindow.geometry("500x300+300+300")
menu_label = Label(LoginWindow,text = "Please login with you Username and Password").grid(row = 0, column = 0,columnspan = 2, padx = 100, pady = 10)
if attempt_made:
incorrect_label = Label(LoginWindow,fg="red",text = "Incorrect username and/or password").grid(row = 5, column = 0,columnspan = 2)
username_label = Label(LoginWindow,text = "Username: ").grid(row = 10, column = 0)
username = StringVar()
username_entry = Entry(LoginWindow,textvariable = username).grid(row = 10, column = 1)
password_label = Label(LoginWindow,text = "Password: ").grid(row = 11, column = 0 )
password = StringVar()
password_entry = Entry(LoginWindow,textvariable = password,show = "*").grid(row = 11, column = 1)
Multichoice_button_0 = Button(LoginWindow,text = "OK", fg = "black", width = "25", height = "2",
command= partial(UserLoginCheckPassword,username,password, LoginWindow)).grid(row = 20, column = 0,padx = 5, pady = 0,columnspan = 1)
Multichoice_button_1 = Button(LoginWindow,text = "Quit", fg = "black", width = "25", height = "2",
command= partial(LoginQuit,LoginWindow)).grid(row = 20, column = 1,padx = 5, pady = 0,columnspan = 1)
LoginWindow.mainloop()
attempt_made = True
return logged_in_user_record[0]
def UserLoginCheckPassword(input_username,input_password, LoginWindow):
global logged_in_user_record
username = input_username.get()
password = input_password.get()
print("\n\nin_user",input_username,", user "+username)
print("in_psw",input_password,", pswd "+password+"\n\n")
If I run this in the main code, then it works fine.
x = UserLogin2() but if I run this from a button press in another function, it all works the same, however the get() return blanks!?
login_button = Button(MainMenuWindow,text = "Login", fg = "black", width = "25", height = "1",command= partial( UserLogin2)).grid(row = 12, column = 0,padx = 5, pady = 5,columnspan = 1) The issue seems to be, if we have a tkinter window with buttons, then a button press creates another tkinter window which has an entry field, get() shows blank, but if the tkinter window with entry field if just called from the main code, not from another windows button press, then get() = the text you entered.
Any ideas please?
Like nested entry/get doesnt work?
buran write Mar-23-2021, 09:45 PM:Please, use proper tags when post code, traceback, output, etc. This time I have added tags for you.
See BBcode help for more info.
Posts: 6,794
Threads: 20
Joined: Feb 2020
Mar-24-2021, 03:54 AM
(This post was last modified: Mar-24-2021, 01:25 PM by deanhystad.)
Multichoice_button_0 and Multichoice_button_1 are both None. If you want to keep a handle to these widgets you need to split making the button and placing the button into two separate commands. If you don't need the handles, don't pretend you are saving them in a variable.
This is a big problem:
LoginWindow = tkinter.Tk() This is how you initialize tkinter. It also creates a window and returns the window handle, but it's primary function is to prepare tkinter for use in your program. This is not how you create a window for a dialog, or a second main window. You can only call Tk() once in your program.
Similarly this is a big problem
LoginWindow.mainloop()
A tkinter program only gets to call mainloop() once. mainloop() will run until the program is shut down (quit) or crashes.
If you fix those problems the next problem you encounter is this:
while login_verified == False and run_program == True: Now that the mainloop() is removed, there is noting preventing this loop from running forever and creating millions of login windows.
There are so many changes required to your code to make it work that I would throw it away and start from scratch. I started by making a login dialog that gets the username and password. It is based off the tkinter.simpledialog.Dialog class. I override the body and buttonbox methods to create my own controls.
import tkinter as tk
from tkinter import simpledialog, messagebox
class LoginDialog(simpledialog.Dialog):
def __init__(self, parent, title='Login'):
super().__init__(parent, title)
def body(self, frame):
"""Places controls in the body of the dialog. Overrides base method"""
self.username = None
self.password = None
self.cancelled = False
tk.Label(frame, text="Username: ").grid(row=0, column=0, padx=5, pady=5)
self.username_entry = tk.StringVar()
tk.Entry(frame, textvariable=self.username_entry).grid(row=0, column=1, pady=10)
tk.Label(frame, text="Password: ").grid(row=1, column=0)
self.password_entry = tk.StringVar()
tk.Entry(frame, textvariable=self.password_entry, show="*") \
.grid(row=1, column=1)
def buttonbox(self):
"""Make buttons at the bottom of the dialog. Overrides base method"""
tk.Button(self, text="Ok", width="10", command=self.ok_pressed) \
.pack(side='left', padx=5, pady=5)
tk.Button(self, text="Cancel", width="10", command=self.cancel_pressed) \
.pack(side='right', padx=5, pady=5)
def ok_pressed(self):
self.username = self.username_entry.get()
self.password = self.password_entry.get()
self.destroy()
def cancel_pressed(self):
self.cancelled = True
self.destroy()
def login():
dialog = LoginDialog(root)
if dialog.cancelled:
print('Login cancelled')
elif dialog.username and dialog.password:
print('Username', dialog.username, '\nPassword', dialog.password)
else:
messagebox.showerror('Login Failed', 'Username and/or Password are Incorrect')
root = tk.Tk()
tk.Button(root, text='Push Me', command=login).pack()
root.mainloop() You can place the password processing in the login() function. Use tkinter Messagebox windows to display messages about successful or unsuccessful login attempts.
Posts: 3
Threads: 1
Joined: Mar 2021
(Mar-24-2021, 03:54 AM)deanhystad Wrote: Multichoice_button_0 and Multichoice_button_1 are both None. If you want to keep a handle to these widgets you need to split making the button and placing the button into two separate commands. If you don't need the handles, don't pretend you are saving them in a variable.
This is a big problem:
LoginWindow = tkinter.Tk() This is how you initialize tkinter. It also creates a window and returns the window handle, but it's primary function is to prepare tkinter for use in your program. This is not how you create a window for a dialog, or a second main window. You can only call Tk() once in your program.
Similarly this is a big problem
LoginWindow.mainloop()
A tkinter program only gets to call mainloop() once. mainloop() will run until the program is shut down (quit) or crashes.
If you fix those problems the next problem you encounter is this:
while login_verified == False and run_program == True: Now that the mainloop() is removed, there is noting preventing this loop from running forever and creating millions of login windows.
There are so many changes required to your code to make it work that I would throw it away and start from scratch. I started by making a login dialog that gets the username and password. It is based off the tkinter.simpledialog.Dialog class. I override the body and buttonbox methods to create my own controls.
import tkinter as tk
from tkinter import simpledialog, messagebox
class LoginDialog(simpledialog.Dialog):
def __init__(self, parent, title='Login'):
super().__init__(parent, title)
def body(self, frame):
"""Places controls in the body of the dialog. Overrides base method"""
self.username = None
self.password = None
self.cancelled = False
tk.Label(frame, text="Username: ").grid(row=0, column=0, padx=5, pady=5)
self.username_entry = tk.StringVar()
tk.Entry(frame, textvariable=self.username_entry).grid(row=0, column=1, pady=10)
tk.Label(frame, text="Password: ").grid(row=1, column=0)
self.password_entry = tk.StringVar()
tk.Entry(frame, textvariable=self.password_entry, show="*") \
.grid(row=1, column=1)
def buttonbox(self):
"""Make buttons at the bottom of the dialog. Overrides base method"""
tk.Button(self, text="Ok", width="10", command=self.ok_pressed) \
.pack(side='left', padx=5, pady=5)
tk.Button(self, text="Cancel", width="10", command=self.cancel_pressed) \
.pack(side='right', padx=5, pady=5)
def ok_pressed(self):
self.username = self.username_entry.get()
self.password = self.password_entry.get()
self.destroy()
def cancel_pressed(self):
self.cancelled = True
self.destroy()
def login():
dialog = LoginDialog(root)
if dialog.cancelled:
print('Login cancelled')
elif dialog.username and dialog.password:
print('Username', dialog.username, '\nPassword', dialog.password)
else:
messagebox.showerror('Login Failed', 'Username and/or Password are Incorrect')
root = tk.Tk()
tk.Button(root, text='Push Me', command=login).pack()
root.mainloop() You can place the password processing in the login() function. Use tkinter Messagebox windows to display messages about successful or unsuccessful login attempts.
Posts: 3
Threads: 1
Joined: Mar 2021
Thanks for your notes.
I have a main window
MainMenuWindow = tk.Tk()
tk.Button(MainMenuWindow,text = "login", fg = "black", width = "25", height = "1", command= partial(UserLogin2,MainMenuWindow)).grid(row = 13, column = 0,padx = 5, pady = 5,columnspan = 1)
tk.mainloop()
also this
def UserLogin2(MainMenuWindow):
attempt_made = False
user_record = ['someblankerrortext']
global login_verified
global run_program
global logged_in_user_record
login_verified = False
run_program = True
logged_in_user_record = [0,"","",0]
while login_verified == False and run_program == True:
LoginWindow = tk.TopLevel()
tk.Label(LoginWindow,text = "Please login with you Username and Password").grid(row = 0, column = 0,columnspan = 2, padx = 100, pady = 10)
if attempt_made:
tk.Label(LoginWindow,fg="red",text = "Incorrect username and/or password").grid(row = 5, column = 0,columnspan = 2)
tk.Label(LoginWindow,text = "Username: ").grid(row = 10, column = 0)
username = StringVar()
tk.Entry(LoginWindow,textvariable = username).grid(row = 10, column = 1)
tk.Label(LoginWindow,text = "Password: ").grid(row = 11, column = 0 )
password = StringVar()
tk.Entry(LoginWindow,textvariable = password,show = "*").grid(row = 11, column = 1)
tk.Button(LoginWindow,text = "OK", fg = "black", width = "25", height = "2", command= partial(UserLoginCheckPassword,username,password)).grid(row = 20, column = 0,padx = 5, pady = 0,columnspan = 1)
tk.Button(LoginWindow,text = "Quit", fg = "black", width = "25", height = "2", command= partial(LoginQuit,LoginWindow)).grid(row = 20, column = 1,padx = 5, pady = 0,columnspan = 1)
tk.mainloop()
attempt_made = True
return logged_in_user_record[0]
and
def UserLoginCheckPassword(input_username,input_password,):
global logged_in_user_record
username = input_username.get()
password = input_password.get()
print("\n\nin_user",input_username,", user "+username)
print("in_psw",input_password,", pswd "+password+"\n\n")
db_connect = sqlite3.connect(database_name) #connects to the database
db_cursor = db_connect.cursor()
db_cursor.execute("SELECT * FROM "+user_ID_table+" WHERE username == '" + username + "' AND password == '"+password+"'")
user_record = db_cursor.fetchall() #selects user record where password and username match and saves it as user_record
global login_verified
if user_record == []: #if the username and password do not match in a record then there data will not be stored.
login_verified = False
else:
login_verified = True
logged_in_user_record = user_record
return
if i run
UserLogin2()
NOT from the login button, but instead from the main code, it works, i have a box, ask 2 entry fields, its check the database, if its wrong, an error message is shown, and repeats until its correct, then returns the user record.
However if i run UserLogin2() from a menu button press, it does not have any value in the get().
i have changed the code to use tk.xxxxx
and some other changes
i have looked at simple dialog, but that is only 1 text entry fields
this is where i am stuck please!
however, if i
Posts: 6,794
Threads: 20
Joined: Feb 2020
You didn't pay any attention to this response to your first post.
Quote:buran write Mar-24-2021, 03:45 AM:
Please, use proper tags when post code, traceback, output, etc. This time I have added tags for you.
See BBcode help for more info.
Go add the appropriate tags and I'll take a look at your code.
Posts: 6,794
Threads: 20
Joined: Feb 2020
Mar-29-2021, 03:55 AM
(This post was last modified: Mar-29-2021, 03:55 AM by deanhystad.)
You still have mainloop() appearing twice in you code. It can only appear once.
You still have this loop that will create thousands of login windows a second once you remove the extra mainloop().
while login_verified == False and run_program == True:
LoginWindow = tk.TopLevel() You did not read enough about simple dialog. I my example I have two entry fields. Not sure how you missed that if you ran the code.
|