Home > Blockchain >  Need to get the multi-digit integer Entry value after the last digit key is pressed
Need to get the multi-digit integer Entry value after the last digit key is pressed

Time:10-04

I am relatively new to tkinter, and very new to coding with classes. My GUI will have a step that asks user to enter in an integer with any number of digits to an Entry(). After the last digit keypress (no keypress in 2000 ms) another function will activate that uses the integer entered. It seems very simple but I cannot seem to get this right. I haven't figured out the .after() part, for now I am just using a binding on the ENTER key. Details on the problems, then the code below. I feel like I am struggling way too much on something that can't be that difficult. Please help.

(Some?) Details:

  • I am getting a bunch of errors leading up to entry input, regarding 'val' not being defined, despite it being defined.
  • Pressing ENTER does not result in any return value (I added a print command to the mouse clicks just to see if 'val' was being assigned)
  • Losing sleep from trying to apply after() function

Code (I tried to strip down to essentials best I could, my problem is near the bottom):

'''

import tkinter as tk
import tkinter.messagebox
kk = 1

class App(tk.Tk):
    
    WIDTH = 1000
    HEIGHT = 520
    
    def __init__(self):
        super().__init__()

        self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
        self.protocol("WM_DELETE_WINDOW", self.on_closing)  # call .on_closing() when app gets closed
                
        self.fr0 = tk.Frame(master=self, background = 'grey')
        self.fr0.pack(fill = 'both', expand = True,  padx = 20, pady = 20)
        
        # configure grid layout (2x1)
        self.fr0.columnconfigure(0, weight = 1)
        self.fr0.columnconfigure(1, weight = 1)
        self.fr0.rowconfigure((1,2,3), weight = 1)
        
        # Title    
        
        self.lab_bcwt = tk.Label(self.fr0, text = 'Title', font=("Roboto Medium", 40), justify = 'center')
        self.lab_bcwt.grid(row = 0,rowspan = 2,  columnspan = 2)
        
        # ===============================
        
        self.fr1 = tk.Frame(self.fr0)#, fg_color=("black","grey"))
        self.fr1.grid(row=2, rowspan = 2, columnspan = 2, sticky = 'nsew', padx = 10, pady = 10)
        self.fr1.columnconfigure(0, weight = 1)
        self.fr1.columnconfigure(1, weight = 1)
        self.fr1.rowconfigure((0,1,2,3,4,5), weight = 1)
        
        # ===============================
        
        self.fr2 = tk.Frame(self.fr1)
        self.fr2.grid(row=0, columnspan = 2, sticky = 'new', padx = 10, pady = 10)
        self.fr2.grid_rowconfigure(0, weight = 1)
        self.fr2.grid_columnconfigure(0, weight = 1)

        # ===============================

        self.lab1 = tk.Label(self.fr2, text = 'This text appears first\n (click to continue)', font=("Ariel", -22), justify = 'center')
        self.lab1.grid( row = 0, columnspan = 2, padx = 10, pady = 5)
        
        
        self.bind("<Button-1>",self.click)
        
        
        
    def on_closing(self, event=0):
        self.destroy()    
    
    def exmp_gps(self):

        self.lab1.destroy()
        self.lab2 = tk.Label(self.fr2, text = 'Then this text appears second,\n telling you to input an integer', font=('Ariel', -22))
        self.lab2.grid(row = 0, column = 0, sticky = 'new', padx = 10, pady = 10)
        self.lab3 = tk.Label(self.fr1, text = 'Any Integer', borderwidth = 2, font = ('Ariel', 12))
        self.lab3.grid(row = 1, column = 0, sticky = 'ne', padx = 10)
        
        
        self.entry1 = tk.Entry(self.fr1, text = 'any integer', justify = 'center')
        self.entry1.grid(row = 1, column = 1, sticky = 'nw',padx = 10)
        self.entry1.configure(font = ('Arial Rounded MT Bold', 13))
                
        def key_pressed(event):
            global val
            val = int(self.entry1.get())
            # print(val)
        
        self.entry1.bind("<KeyRelease>", key_pressed)
        
        # Ideally 
        
        
        self.entry1.bind("<Return>", print(['Function using', val 1]))
    
    def click(self,event):
        global kk
        if kk == 1:
            self.exmp_gps()
        if kk > 1:
            print(['Function using', val 1])
    
if __name__ == "__main__":
    app = App()
    app.mainloop()
    

'''

CodePudding user response:

There is few problems in code.

bind needs function's name without () but you use print() so it first runs print() (which returns None) and later it binds None to <Return>. You could bind lambda event:print(...) to run print() when you press Enter.

Code could be more readable if you would use normal self.val instead of global val and if normal function in class def key_pressed(self, event): instead of nested function.

Everytime when you click button then it runs clik() and it runs self.exmp_gps() and it creates new Entry. You should increase kk in click() to run self.exmp_gps() only once. And to make it more readable you could use ie. self.visible = False and later set self.visible = True

You think it can be simple to activate function 2000ms after last keypress - but it is not. It would have to use after() and remeber its ID and time when it was created (to delete it if next key will be pressed before 2000ms, and use new after()).

Using Enter is much, much simpler.


Full code with changes.

I added after() but I didn't test it - maybe in some situations it may run function many times.

import tkinter as tk
import tkinter.messagebox

class App(tk.Tk):
    
    WIDTH = 1000
    HEIGHT = 520
    
    def __init__(self):
        super().__init__()

        self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
        self.protocol("WM_DELETE_WINDOW", self.on_closing)  # call .on_closing() when app gets closed
                
        self.fr0 = tk.Frame(master=self, background='grey')
        self.fr0.pack(fill='both', expand=True, padx=20, pady=20)
        
        # configure grid layout (2x1)
        self.fr0.columnconfigure(0, weight=1)
        self.fr0.columnconfigure(1, weight=1)
        self.fr0.rowconfigure((1, 2, 3), weight=1)
        
        # Title    
        
        self.lab_bcwt = tk.Label(self.fr0, text='Title', font=("Roboto Medium", 40), justify='center')
        self.lab_bcwt.grid(row=0, rowspan=2, columnspan=2)
        
        # ===============================
        
        self.fr1 = tk.Frame(self.fr0)#, fg_color=("black","grey"))
        self.fr1.grid(row=2, rowspan=2, columnspan=2, sticky='nsew', padx=10, pady=10)
        self.fr1.columnconfigure(0, weight=1)
        self.fr1.columnconfigure(1, weight=1)
        self.fr1.rowconfigure((0, 1, 2, 3, 4, 5), weight=1)
        
        # ===============================
        
        self.fr2 = tk.Frame(self.fr1)
        self.fr2.grid(row=0, columnspan=2, sticky='new', padx=10, pady=10)
        self.fr2.grid_rowconfigure(0, weight=1)
        self.fr2.grid_columnconfigure(0, weight=1)

        # ===============================

        self.lab1 = tk.Label(self.fr2, text='This text appears first\n (click to continue)', font=("Ariel", -22), justify='center')
        self.lab1.grid(row=0, columnspan=2, padx=10, pady=5)
        
        self.bind("<Button-1>", self.click)
        
        self.val = 0
        self.visible = False
        self.after_id = None
        
    def on_closing(self, event=0):
        self.destroy()    

    def key_pressed(self, event):
        self.val = int(self.entry1.get())
        print('[key_pressed]', self.val)
        
        if self.after_id:
            print('[key_pressed] cancel after:', self.after_id)
            self.after_cancel(self.after_id)
            self.after_id = None
            
        self.after_id = self.after(2000, self.process_data)
        print('[key_pressed] create after:', self.after_id)
        
    def process_data(self):
        print('[process_data]')
        
    def exmp_gps(self):

        self.lab1.destroy()
        
        self.lab2 = tk.Label(self.fr2, text='Then this text appears second,\n telling you to input an integer', font=('Ariel', -22))
        self.lab2.grid(row=0, column=0, sticky='new', padx=10, pady=10)
        
        self.lab3 = tk.Label(self.fr1, text='Any Integer', borderwidth=2, font=('Ariel', 12))
        self.lab3.grid(row=1, column=0, sticky='ne', padx=10)
        
        self.entry1 = tk.Entry(self.fr1, text='any integer', justify='center')
        self.entry1.grid(row=1, column=1, sticky='nw', padx=10)
        self.entry1.configure(font=('Arial Rounded MT Bold', 13))
        
        self.entry1.bind("<KeyRelease>", self.key_pressed)
        self.entry1.bind("<Return>", lambda event:print('[Return] Function using', self.val))
    
    def click(self, event):
        if not self.visible:
            self.visible = True
            self.exmp_gps()
        else:
            print('[click] Function using', self.val)
    
if __name__ == "__main__":
    app = App()
    app.mainloop()
  • Related