TKinter Entry 验证在设置其 StringVar 后不起作用

TKinter Entry validation not working after setting its StringVar

我有一个 TKinter 条目小部件,我想在其中验证输入,一切都按预期工作。

但是当我设置 Entry 小部件的 StringVariable 时,不再调用验证函数。 有人可以向我解释这种行为吗?

这是我的问题示例,我在其中验证输入是否为数字

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()

我希望能够在不丢失验证功能的情况下更改 StringVar 的值(以及因此更改 Entry Widget 的内容)。

这就是 canonical documentation 关于同时使用变量和条目验证的说法:

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

在您的例子中,当您调用 self.var1.set("25") 时,会触发验证函数。发生这种情况时,向验证函数发送一个空字符串。这是因为 %S 表示要 插入的数据 而您没有插入文本,而是 设置 文本.这会导致您的函数 return False,因此验证被关闭。

解决方案是不使用 textvariable 选项。相反,使用 insert 直接将文本插入小部件,这会将值“25”传递给您的验证函数。

self.entry.insert(0, "25")