Skip to content
Advertisement

TKinter Entry validation not working after setting its StringVar

I have a TKinter entry widget where i want to validate the input, and everything works as expected.

But when I set the StringVariable of the Entry widget the validation function is no more called. Can someone explain me this behavior?

Here is an example of my problem where i validate whether the input is a digit or not

import tkinter as tk


class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.var1 = tk.StringVar()

        valid_cmd = (self.register(self.on_validate), '%S')
        self.entry = tk.Entry(self, textvariable=self.var1, validate="key", validatecommand=valid_cmd)
        self.entry.pack(side="top", fill="x")

        self.var1.set("25")         # comment out this line and validation function works as expected

    def on_validate(self, S):
        print("in validation function")
        if S.isdigit():
            return True
        else:
            return False


if __name__ == "__main__":
    root = tk.Tk()
    tk.Tk.geometry(root, '200x40')
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

I want to be able to change the value of the StringVar (and therefore the content of the Entry Widget) without loosing the validation function.

Advertisement

Answer

This is what the canonical documentation says about using variables and entry validation together:

In general, the textVariable and validateCommand can be dangerous to mix. Any problems have been overcome so that using the validateCommand will not interfere with the traditional behavior of the entry widget. Using the textVariable for read-only purposes will never cause problems. The danger comes when you try set the textVariable to something that the validateCommand would not accept, which causes validate to become none (the invalidCommand will not be triggered). The same happens when an error occurs evaluating the validateCommand.

Primarily, an error will occur when the validateCommand or invalidCommand encounters an error in its script while evaluating or validateCommand does not return a valid Tcl boolean value. The validate option will also set itself to none when you edit the entry widget from within either the validateCommand or the invalidCommand. Such editions will override the one that was being validated. If you wish to edit the entry widget (for example set it to {}) during validation and still have the validate option set, you should include the command

In your case, when you call self.var1.set("25"), that triggers the validation function. When that happens, the validation function is sent an empty string. This is due to the fact that %S represents data to be inserted and you aren’t inserting text, you are setting the text. That causes your function to return False, and thus validation is turned off.

The solution is to not use the textvariable option. Instead, directly insert text into the widget with insert, which will pass the value “25” to your validation function.

self.entry.insert(0, "25")
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement