不明白Tkinter入境箱有效性

时间:2017-04-12 05:23:59

标签: python-3.x tkinter

我有一个带有输入框的tkinter GUI我想只允许数字。有人可以向我解释验证中的每个命令/代码行。我不了解vcmd变量和所有'%i' '%S'东西。谢谢:))

更新: 我有一个不同的应用程序使用此vcmd命令,并且完全不理解它。这是我的验证码:

def validate(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name):
    if not int(action):
        return True
    elif text in '0123456789.-+':
        try:
            float(value_if_allowed)
            return True
        except ValueError:
            return False
    else:
        return False

我不明白为什么在这段代码中我需要所有这些:

action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name

为什么我需要所有这些特定于我的验证代码才能正常运行它们有什么用途? 您提供的文档很有意义,但其中一些'%s'%'%i'对于我的特定代码来说似乎没有什么东西,但它只适用于包括它们在内的所有代码:

vcmd = (self.master.register(self.validate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')

我也想知道self.master.register会做什么,我仍然无法想出那个。

1 个答案:

答案 0 :(得分:1)

如果您不需要任何特殊参数,则无需致电register。例如,以下代码将正确调用do_validation而不带任何参数:

import tkinter as tk

def do_validation():
    value = entry.get()
    if value == "" or value.isnumeric():
        return True
    return False

root = tk.Tk()
entry = tk.Entry(root, validate='key', validatecommand=do_validation)
entry.pack(fill="x", padx=20, pady=20)

root.mainloop()

然而,在上述情况下,验证将始终是一个字符。这是因为验证在字符插入到条目小部件之前发生(即:第一次调用它时,entry.get()将返回一个空字符串)。验证的全部要点是防止非法字符,因此在插入字符之前而不是之后调用命令是有意义的。

这就是特殊参数有用的原因 - 它们提供了足够的上下文,以便在将字符插入窗口小部件之前判断字符是否合法。

register如何有用

Tkinter是Tcl解释器的包装器,因为tk(tkinter背后的核心技术)是在Tcl中实现的。 Tcl是一种编程语言,就像python一样。

在Tcl程序中,您将使用如下验证功能:

proc do_validation(new_value) {
    return $new_value == "" || [string is integer $new_value]
}
entry .entry -validate key --validatecommand [list do_validation %P]

当Tcl检测到更改时,它会对参数执行替换,然后使用替换参数调用已定义的过程。例如,如果键入“A”,则%P将转换为"A",并且调用该函数时将"A"作为唯一参数。

在Tkinter的情况下,没有直接的推论来定义具有在运行时替换的参数的函数。

不幸的是,验证功能在tkinter包装器中没有很好地实现,所以为了正确使用验证,我们必须使用一个小的解决方法,以便将这些特殊参数传递给我们的函数。

register的作用是创建一个调用python命令的新Tcl命令。它还创建了一个新的python命令,它是对这个新Tcl命令的引用。您可以像使用任何其他python命令一样使用此引用。

一个简单的例子

在最简单的情况下,您需要的只是在允许编辑时字符串的样子。然后,您可以决定编辑是否会导致有效输入,或者是否会导致无效输入。如果编辑不会产生有效输入,您可以在实际发生之前拒绝编辑。

如果允许编辑,则表示值的特殊参数是%P 1 。我们可以修改我们注册的函数来接受这个参数,我们可以在注册时添加这个参数:

def do_validation(new_value):
    return new_value == "" or new_value.isnumeric()

...
vcmd = (root.register(do_validation), '%P')
entry = tk.Entry(..., validatecommand=vcmd)

这样,当底层Tcl代码检测到更改时,它将调用创建的新Tcl命令,传入一个对应于特殊%P替换的参数。

1 验证的所有机制都在tcl文档中详细描述:http://tcl.tk/man/tcl8.5/TkCmd/entry.htm#M7