在 tk.Entry 文本变量上调用 tk.StringVar.set() 会导致 validate="focusout" 停止调用

Calling tk.StringVar.set() on a tk.Entry textvariable causes validate="focusout" to stop getting called

问题在标题中,本质上是:如何让 validatecommand 回调在设置条目的 textvariable 后继续被调用?这是最小工作示例 (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()

请注意,第二个 tk.Entry 小部件可以让第一个小部件失去焦点,这是我们试图捕获的事件。

就像现在的代码一样,当您 运行 它时,您可以更改一次顶部条目小部件的文本。它会正确设置为 Set Text. 然后,如果您尝试再次更改条目的文本,新文本将出现在小部件中,但回调不会发生。

另一方面,如果您注释掉 sv.set('Set Text.') 代码,此行为将完全消失,您可以根据需要多次调用回调。

How can I have the sv.set() functionality, while still maintaining the callback getting called every time the Entry widget loses focus?

这在 Tk manual page for entry 中讨论:

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.

据推测,这样做是为了避免无限递归。

您可以运行这个(而不是给定的 Tcl 代码,after idle {%W config -validate %v}

root.after_idle(lambda: e.config(validate="focusout"))

从回调中安排小部件的重新配置以再次启用验证(在更改您的源之后 e 是正确的 Entry 小部件,即不是第二个)。