python - 在 tkinter 中交互式验证条目小部件内容

标签 python validation tkinter textbox

在 tkinter Entry 小部件中交互式验证内容的推荐技术是什么?

我已阅读有关使用 validate=Truevalidatecommand=command 的帖子,这些功能似乎受到限制,即如果validatecommand 命令更新 Entry 小部件的值。

鉴于这种行为,我们是否应该绑定(bind) KeyPressCutPaste 事件并监控/更新我们的 Entry 小部件的值(value)通过这些事件? (以及我可能错过的其他相关事件?)

或者我们应该完全忘记交互式验证,只对 FocusOut 事件进行验证?

最佳答案

正确答案是,使用小部件的 validatecommand 属性。不幸的是,这个特性在 Tkinter 世界中被严重记录不足,尽管它在 Tk 世界中被充分记录。即使没有很好地记录它,它也有您进行验证所需的一切,而无需借助绑定(bind)或跟踪变量,或在验证过程中修改小部件。

诀窍是要知道您可以让 Tkinter 将特殊值传递给您的 validate 命令。这些值为您提供了决定数据是否有效所需的所有信息:编辑前的值、编辑后的值(如果编辑有效)以及其他一些信息。但是,要使用这些,您需要做一些巫术来将这些信息传递给您的 validate 命令。

注意:验证命令返回 TrueFalse 很重要。其他任何事情都会导致小部件的验证被关闭。

这是一个只允许小写的例子。出于说明目的,它还打印所有特殊值的值。它们并非都是必需的。你很少需要超过一两个。

import tkinter as tk  # python 3.x
# import Tkinter as tk # python 2.x

class Example(tk.Frame):

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

        # valid percent substitutions (from the Tk entry man page)
        # note: you only have to register the ones you need; this
        # example registers them all for illustrative purposes
        #
        # %d = Type of action (1=insert, 0=delete, -1 for others)
        # %i = index of char string to be inserted/deleted, or -1
        # %P = value of the entry if the edit is allowed
        # %s = value of entry prior to editing
        # %S = the text string being inserted or deleted, if any
        # %v = the type of validation that is currently set
        # %V = the type of validation that triggered the callback
        #      (key, focusin, focusout, forced)
        # %W = the tk name of the widget

        vcmd = (self.register(self.onValidate),
                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
        self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
        self.text = tk.Text(self, height=10, width=40)
        self.entry.pack(side="top", fill="x")
        self.text.pack(side="bottom", fill="both", expand=True)

    def onValidate(self, d, i, P, s, S, v, V, W):
        self.text.delete("1.0", "end")
        self.text.insert("end","OnValidate:\n")
        self.text.insert("end","d='%s'\n" % d)
        self.text.insert("end","i='%s'\n" % i)
        self.text.insert("end","P='%s'\n" % P)
        self.text.insert("end","s='%s'\n" % s)
        self.text.insert("end","S='%s'\n" % S)
        self.text.insert("end","v='%s'\n" % v)
        self.text.insert("end","V='%s'\n" % V)
        self.text.insert("end","W='%s'\n" % W)

        # Disallow anything but lowercase letters
        if S == S.lower():
            return True
        else:
            self.bell()
            return False

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

有关调用 register 方法时幕后发生的事情的更多信息,请参阅 Why is calling register() required for tkinter input validation?

有关规范文档,请参阅 Validation section of the Tcl/Tk Entry man page

关于python - 在 tkinter 中交互式验证条目小部件内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4140437/

相关文章:

python - 为什么按下按钮后变量会恢复为原始值(Tkinter)?

python - 发送低级原始 tcp 数据包 python

hibernate :发现: float ,预期: double

asp.net - 以编程方式将验证控件添加到 asp.net 页面

python - 禁用 tkinter ttk 缩放小部件

python - 在 Tkinter Python 中删除

python - 如何创建一个按条件填充创建列表的函数

python - 如何使用 Scipy 生成特定分布的随机值

python - 给定索引列表的数组的部分和

java - 在哪里可以找到 javax.validation.* 的实现?