Python Forum
.get() invoke after a button nested press
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
.get() invoke after a button nested press
#1
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.
Reply
#2
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.
Reply
#3
(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.
Reply
#4
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
Reply
#5
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.
Reply
#6
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  tkinter.TclError: can't invoke "canvas" command cybertooth 8 6,014 Feb-23-2023, 06:58 PM
Last Post: deanhystad
  [Tkinter] _tkinter.TclError: can't invoke "destroy" command: application has been destroyed knoxvilles_joker 6 15,617 Apr-25-2021, 08:41 PM
Last Post: knoxvilles_joker
Question closing a "nested" window with a button in PySimpleGUI and repeating this process Robby_PY 9 13,610 Jan-18-2021, 10:21 PM
Last Post: Serafim
  tkinter touchscreen scrolling - button press makes unwanted scrolling nanok66 1 4,012 Dec-28-2020, 10:00 PM
Last Post: nanok66
  Anytime I press the button, the result is depicted Jionni 2 2,235 Feb-24-2020, 10:08 AM
Last Post: Jionni
  [PySimpleGui] How to alter mouse click button of a standard submit button? skyerosebud 3 5,029 Jul-21-2019, 06:02 PM
Last Post: FullOfHelp
  [Tkinter] how to input a random entry with each button press? nadavrock 1 6,410 Jun-17-2019, 05:28 AM
Last Post: Yoriz
  [Tkinter] Spawn sub-window with button press malonn 3 5,895 Oct-28-2018, 02:56 PM
Last Post: malonn
  [Tkinter] Updating Label After Button Press malonn 7 5,717 Aug-23-2018, 10:52 PM
Last Post: malonn
  [Tkinter] Problem with changing label text on button press xk2006x 1 5,583 Jun-02-2017, 06:00 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020