Search code examples
pythontkintertkinter-entry

Tkinter validate "key" is returning an empty string


So I have this project where a scanner scans a barcode (which works as if a keyboard entered in the input) and I want it to have it print out the input once there is a change in the "Entry" box but instead it is printing out an empty string and I used a list on it just to see if it was an empty string or something else. This is a snippet of my project.

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("550x250")
        self.title("Testing Proctor Reader")

        self.mainPage()
        
    def mainPage(self):
        for i in self.winfo_children():
            i.destroy()

        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(2, weight=1)
        startBtn = tk.Button(self, text='Start Scanning',bg="green",fg="white", command=self.scannerStart)
        startBtn.grid(row=1, column=1, padx=20, pady=20)
        startBtn.grid_rowconfigure(0, weight=1)
        startBtn.grid_columnconfigure(0, weight=1)

    def inputChange(self):
        print([self.userInput.get()])

        self.userInput.delete(0, 'end')
        self.scannerStart()

    def scannerStart (self):
        for i in self.winfo_children():
            i.destroy()

        self.scanning = True

        self.userInput = tk.Entry(self, validate="key", validatecommand=self.inputChange)
        self.userInput.grid(row=2, column=1, padx=20, pady=20)
        self.userInput.focus()

app = App()
app.mainloop()

the problem is somewhere around the self.userInput and the inputChange() function


Solution

  • The get method returns what is in the entry widget. In the validation function, the actual value of the entry isn't changed unless and until the function returns a truthy value.

    You can have tkinter pass in various values to the validation function, such as the data being added or the value of the entry if the data is accepted.

    Also, the validation function should not directly alter the entry widget. If you don't want the entry widget to accept the potential change you can return False.

    For example, to have the value of the entry passed to your function you first need to modify inputChanged to accept this value as a parameter:

    def inputChange(self, new_value):
        print(f"new_value: {new_value}")
        ...
    

    Next, you can register this function and have the validate command pass in the potential new value like so:

    def scannerStart (self):
        ...
        validate_command = (self.register(self.inputChange), "%P")
        self.userInput = tk.Entry(self, validate="key", validatecommand=self.inputChange)
        ...
    

    In the above example, %P is a placeholder that represents the future value of the entry widget if the edit is allowed. The edit will be allowed if this function returns True, and won't be allowed if the function returns False.

    Instead of %P, you could use %S to have passed in the string being inserted.

    For more information about entry validation and to see all of the available placeholders, see this answer to the question Interactively validating Entry widget content in tkinter