本文介绍了在 tkinter 中交互式验证条目小部件内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the recommended technique for interactively validating content in a tkinter Entry widget?

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

I've read the posts about using validate=True and validatecommand=command, and it appears that these features are limited by the fact that they get cleared if the validatecommand command updates the Entry widget's value.

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

Given this behavior, should we bind on the KeyPress, Cut, and Paste events and monitor/update our Entry widget's value through these events? (And other related events that I might have missed?)

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

Or should we forget interactive validation altogether and only validate on FocusOut events?

推荐答案

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

The correct answer is, use the validatecommand attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.

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

The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.

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

Note: it's important that the validation command returns either True or False. Anything else will cause the validation to be turned off for the widget.

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

Here's an example that only allows lowercase. It also prints the values of all of the special values for illustrative purposes. They aren't all necessary; you rarely need more than one or two.

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:
")
        self.text.insert("end","d='%s'
" % d)
        self.text.insert("end","i='%s'
" % i)
        self.text.insert("end","P='%s'
" % P)
        self.text.insert("end","s='%s'
" % s)
        self.text.insert("end","S='%s'
" % S)
        self.text.insert("end","v='%s'
" % v)
        self.text.insert("end","V='%s'
" % V)
        self.text.insert("end","W='%s'
" % 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 方法时幕后发生的更多信息,请参阅 为什么 tkinter 输入验证需要调用 register()?

For more information about what happens under the hood when you call the register method, see Why is calling register() required for tkinter input validation?

有关规范文档,请参阅 Tcl/Tk 条目的验证部分手册页

For the canonical documentation see the Validation section of the Tcl/Tk Entry man page

这篇关于在 tkinter 中交互式验证条目小部件内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 16:22
查看更多