tkinter 中的小部件验证

编程入门 行业动态 更新时间:2024-10-28 04:30:18
本文介绍了tkinter 中的小部件验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

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

I want the user to be able to enter an integer value in the Spinbox widget. If the value entered is not an integer or is an integer outside the Spinbox limits, as soon as the Spinbox loses focus, the value in the Spinbox's content must revert to a default value.

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

In the example code, I use the Entry widget just for the Spinbox can lose focus.

如果用户返回 Spinbox 输入新值,则不会验证其输入.我在 交互式验证 tkinter 中的 Entry 小部件内容 中确认了马尔科姆的评论,即validatecommand=command 一旦此命令更新小部件的值,特性就会被清除.

If the user comes back to Spinbox to enter a new value, his entry is not validated. I confirm Malcolm's remark in Interactively validating Entry widget content in tkinter that the validatecommand=command feature gets cleared as soon as this command updates the widget's value.

有没有办法让在 Spinbox 中输入的值重复验证而不仅仅是一次?

Is there a way to get the value entered in the Spinbox repeatedly validated and not just once?

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

推荐答案

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

I found a great explanation here (in the last paragraph of the chapter Validation):

http://stupidpythonideas.blogspot.fr/2013/12/tkinter-validation.html

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

If your validatecommand (or invalidcommand) modifies the Entry directly or indirectly (e.g., by calling set on its StringVar), the validation will get disabled as soon as your function returns. (This is how Tk prevents an infinite loop of validate triggering another validate.) You have to turn it back on (by calling config). But you can't do that from inside the function, because it gets disabled after your function returns.

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

But you need to apply some changes to be able to use this trick.

您需要使 Spinbox 成为一个实例属性,使用 self :

You need to make the Spinbox an instance attribute, with self :

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_count.after_idle(...) :

And then you can call self.items_count.after_idle(...) inside the validate method :

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

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

更多推荐

[db:关键词]

本文发布于:2023-04-30 06:29:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1390826.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:部件   tkinter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!