ttk.Spinbox 绑定命令中的消息框导致无限的弹出流 windows

Messagebox in ttk.Spinbox bound command causes an infinite stream of pop up windows

我正在从事一个个人学习项目,该项目包含一个生成密码的简单 GUI。用户可以 select 密码中包含每种类型(字母、数字和符号)的字符数,也可以让应用程序选择一个随机组合。密码长度限制为 128 个字符。我想要做的是在用户尝试增加超过 128 个限制的字符数时显示一条消息。

到目前为止,我尝试的是在绑定到 <<Increment>> 事件的函数中包含一个检查,当按下旋转框中的增量按钮时,该事件将被调用。有一个 if 语句检查剩余的可用字符,如果该值为零,则弹出 messagebox.showwarnning 通知用户最大字符数为 128。

消息出现,但当单击确定按钮时,消息关闭,只是一次又一次地弹出,停止它的唯一方法是杀死整个东西。我还尝试将消息框移动到绑定到旋转框命令的函数,结果相同。关于如何解决这个问题或我做错了什么的任何想法?谢谢

这是小部件的简化版本:

from tkinter import *
from tkinter import ttk
from tkinter import messagebox


class App(Tk):
    def __init__(self):
        super().__init__()
        self.title('Sample')
        self.geometry('300x100')
        Selector(self).pack()

class Selector(ttk.Frame):
        def __init__(self, container):
            super().__init__(container)
            self.max_length = 10
            self.input = IntVar(0);

            self.label = ttk.Label(self, text="Quantity: ").pack()
            self.spinbox = ttk.Spinbox(self, from_=0,
                                       to=self.max_length,
                                       textvariable=self.input)
            self.spinbox.pack()
            self.spinbox.bind('<<Increment>>', lambda e: self.check_length(e))

        def check_length(self, e):
            if self.input.get() == 10:
                messagebox.showwarning("Max length reached", "Too much!")
            

        
if __name__ == "__main__":
    app = App()
    app.mainloop()

似乎关闭消息框会重新触发 <<Increment>> 事件。我想我已经找到了一个解决方法:关闭消息框后焦点从旋转框中移除,并且只有当旋转框有焦点时才会检查旋转框的值(这意味着用户实际上已经点击了它)。

from tkinter import *
from tkinter import ttk
from tkinter import messagebox


class App(Tk):
    def __init__(self):
        super().__init__()
        self.title('Sample')
        self.geometry('300x100')
        Selector(self).pack()

class Selector(ttk.Frame):
        def __init__(self, container):
            super().__init__(container)
            self.max_length = 10
            self.input = IntVar(self, 0);

            self.label = ttk.Label(self, text="Quantity: ").pack()
            self.spinbox = ttk.Spinbox(self, from_=0,
                                       to=self.max_length,
                                       textvariable=self.input)
            self.spinbox.pack()
            self.spinbox.bind('<<Increment>>', lambda e: self.check_length(e))

        def check_length(self, e):
            if str(self.spinbox) != str(self.focus_get()):
                return
            if self.input.get() == 10:
                messagebox.showwarning("Max length reached", "Too much!")
                self.focus_set()



if __name__ == "__main__":
    app = App()
    app.mainloop()

注意:这并没有解决底层问题(事实上 <<Increment>> 在关闭消息框后无限触发),它只是防止无限重新打开消息框。