The question's in the title, essentially: how do I get the validatecommand
callback to continue being called after setting the Entry's textvariable
? Here's the Minimum Working Example (MWE):
import tkinter as tk
root = tk.Tk()
sv = tk.StringVar()
def callback():
print(sv.get())
sv.set('Set Text.')
return True
e = tk.Entry(root, textvariable=sv, validate="focusout",
validatecommand=callback)
e.grid()
e = tk.Entry(root)
e.grid()
root.mainloop()
Note that the second tk.Entry
widget is there to allow the first one to lose focus, which is the event we're trying to capture.
As the code is now, when you run it, you can change the top Entry widget's text once. It'll correctly get set to Set Text.
Then, if you try to change the Entry's text again, the new text will be in the widget, but the callback doesn't happen.
On the other hand, if you comment out the sv.set('Set Text.')
code, this behavior completely disappears, and the callback gets called as many times as you wish.
How can I have the
sv.set()
functionality, while still maintaining the callback getting called every time the Entry widget loses focus?
This is discussed in the Tk manual page for entry
:
The
validate
option will also set itself tonone
when you edit the entry widget from within either thevalidateCommand
or theinvalidCommand
. Such editions will override the one that was being validated.
Presumably, this is done to avoid infinite recursion.
You can run this (instead of the given Tcl code, after idle {%W config -validate %v}
)
root.after_idle(lambda: e.config(validate="focusout"))
from the callback to schedule a reconfiguration of the widget to enable validation again (after changing your sources so that e
is the right Entry
widget, i.e. not the second one).