在tk.Entry textvariable上调用tk.StringVar.set()导致validate =“ focusout”停止被调用

时间:2018-09-29 19:36:11

标签: python python-3.x tkinter callback tkinter-entry

问题本质上是标题:在设置条目的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小部件可以使第一个小部件失去焦点,这是我们试图捕获的事件。

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

另一方面,如果注释掉sv.set('Set Text.')代码,则此行为将完全消失,并且回调将被调用任意多次。

  

我如何拥有sv.set()功能,同时仍保持每次Entry小部件失去焦点时都会调用回调?

1 个答案:

答案 0 :(得分:2)

这在Tk manual page for entry中进行了讨论:

  

<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:gravity="center_vertical" android:orientation="horizontal"> <Spinner android:id="@+id/quest_selector_spinner" android:layout_width="match_parent" android:layout_height="wrap_content" android:dropDownWidth="wrap_content" android:padding="5dp"/> </LinearLayout> validate内部编辑条目窗口小部件时,none选项还将自身设置为validateCommand。这样的版本将覆盖正在验证的版本。

大概是为了避免无限递归。

您可以运行它(代替给定的Tcl代码invalidCommand

after idle {%W config -validate %v}

从回调中安排小部件的重新配置以再次启用验证(更改源之后,使root.after_idle(lambda: e.config(validate="focusout")) 是正确的e小部件,即不是第二个小部件)。