Python tkinter中的小部件验证

Python tkinter中的小部件验证,python,validation,tkinter,widget,Python,Validation,Tkinter,Widget,我希望用户能够在Spinbox小部件中输入一个整数值。如果输入的值不是整数或是超出Spinbox限制的整数,则一旦Spinbox失去焦点,Spinbox内容中的值必须恢复为默认值 在示例代码中,我使用Entry小部件只是因为Spinbox可能会失去焦点 如果用户返回到Spinbox输入新值,则其输入不会被验证。 我确认马尔科姆的评论,即只要该命令更新小部件的值,validatecommand=command功能就会被清除 有没有办法让输入到Spinbox中的值反复验证而不是一次 from tki

我希望用户能够在Spinbox小部件中输入一个整数值。如果输入的值不是整数或是超出Spinbox限制的整数,则一旦Spinbox失去焦点,Spinbox内容中的值必须恢复为默认值

在示例代码中,我使用Entry小部件只是因为Spinbox可能会失去焦点

如果用户返回到Spinbox输入新值,则其输入不会被验证。 我确认马尔科姆的评论,即只要该命令更新小部件的值,
validatecommand=command
功能就会被清除

有没有办法让输入到Spinbox中的值反复验证而不是一次

from tkinter import *


class GUI:

    def __init__(self):
        # root window of the whole program
        self.root = Tk()
        self.root.title('Validate Spinbox')

        # registering validate and invalid commands
        validate_cmd = (self.root.register(self.validate), '%P')
        invalid_cmd = (self.root.register(self.invalid))

        # creating a Label
        items_lbl = Label(self.root, text="# of items (5-10):")
        items_lbl.grid(row=0, column=0)

        # creating a Spinbox widget
        self.items_var = StringVar()
        self.items_var.set(7)
        items_count = Spinbox(self.root, textvariable=self.items_var,
                              from_=5, to=10, width=4, validate='focusout',
                              validatecommand=validate_cmd,
                              invalidcommand=invalid_cmd)
        items_count.grid(row=0, column=1)

        # creating an Entry widget
        self.entry_var = StringVar()
        self.entry_var.set("Input some text here")
        text_entry = Entry(self.root, textvariable=self.entry_var)
        text_entry.grid(row=1, column=0)

    def validate(self, entry):
        try:
            value = int(entry)
            valid = value in range(5, 11)
        except ValueError:
            valid = False
        if not valid:
            self.root.bell()
        return valid

    def invalid(self):
        self.items_var.set(7)


if __name__ == '__main__':
    main_window = GUI()
    mainloop()

我在这里找到了一个很好的解释(在《验证》一章的最后一段中):

如果validatecommand(或invalidcommand)直接或间接地修改条目(例如,通过调用其StringVar上的set),则一旦函数返回,验证将被禁用。(这就是Tk如何防止验证的无限循环触发另一个验证。)您必须重新打开它(通过调用config)。但不能从函数内部执行此操作,因为函数返回后它会被禁用

但您需要应用一些更改才能使用此技巧

您需要使用
self
Spinbox
作为实例属性:

self.items_count = Spinbox(self.root, textvariable=self.items_var,
                      from_=5, to=10, width=4, validate='focusout',
                      validatecommand=validate_cmd,
                      invalidcommand=invalid_cmd)
self.items_count.grid(row=0, column=1)
然后您可以在
validate
方法中调用
self.items\u count.after\u idle(…)

def validate(self, entry):
    try:
        value = int(entry)
        valid = value in range(5, 11)
    except ValueError:
        valid = False
    if not valid:
        self.root.bell()
        self.items_count.after_idle(lambda: self.items_count.config(validate='focusout'))
    return valid

validatecommand
保持正常,是绑定到
focusout
事件的
validate
参数reset@PRMoureu:谢谢你的回复!!!是否有办法不重置验证参数?最好是:由于我是Python新手,如果您能修改我的代码,我将不胜感激。很高兴能提供帮助,多亏了这个博客的作者,我也学到了一些东西