代码之家  ›  专栏  ›  技术社区  ›  Håkon Hægland

之后未调用Entry validatecommandtkinter.messagebox.showwarning显示警告()已调用

  •  2
  • Håkon Hægland  · 技术社区  · 3 年前

    Entry ,下面是一个最小的示例:

    import tkinter as tk
    from tkinter import messagebox
    
    class MainWindow(tk.Tk):
        """ The main window
        """
        def __init__(self):
            tk.Tk.__init__(self)
            self.configure_window()
    
    
        def configure_window(self):
            """ Configure the main window
            """
            self.geometry("600x400")
            self.title("Testing entry validate command")
            self.bind_all('<Control-w>', lambda e: self.destroy())
            var1 = tk.StringVar(value="0")
            vcmd = (self.register(self.validate_input))
            entry1 = tk.Entry(
                self,
                textvariable=var1,
                validate='all',
                validatecommand=(vcmd, '%P'))
            entry1.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
    
        def validate_input(self, txt):
            """ Validate that the input only contains digits
            """
            print(txt)
            if str.isdigit(txt) or txt == "":
                return True
            messagebox.showwarning(
                "Alert", "Please enter a positive integer")
            return False
    
    
    def main():
        window = MainWindow()
        window.mainloop()
    
    main()
    

    validate_input() 在第一次显示警告消息后,不会调用方法。例如,如果用户在条目中输入“0”、“1”、“r”(三个按键), 验证输入() 为每个按键笔划调用,并为最后一个按键笔划(字母“r”)显示警告消息框。接下来,如果用户继续在条目中键入(在警告消息框中按“确定”之后),则 验证输入()

    有什么问题吗?

    3 回复  |  直到 3 年前
        1
  •  2
  •   Delrius Euphoria TheLizzard    3 年前

    this 问题没有正确答案,我无法将其作为副本关闭,但您只需要以下内容:

    def validate_input(self, txt):
        """ Validate that the input only contains digits
        """
        print(txt)
        if txt.isdigit() or txt == "":
            return True
        else:
            messagebox.showwarning("Alert", "Please enter a positive integer")
            self.entry1.config(validate='all',validatecommand=(self.vcmd, '%P')) # Set the validation back
            return False
    

    一定要说 self.entry1 self.vcmd :

    self.vcmd = (self.register(self.validate_input))
    self.entry1 = tk.Entry(self,textvariable=var1,validate='all',validatecommand=(self.vcmd, '%P'))
    self.entry1.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
    

    虽然我不太清楚,为什么会这样,但这解决了它。看起来像是 messagebox 小部件丢失其 validation 我们还得再把它放回去。

    validate='all' validate='key'

    self.entry1 = tk.Entry(self,textvariable=var1,validate='key',validatecommand=(self.vcmd, '%P'))
    
        2
  •  3
  •   Bryan Oakley    3 年前

    validate “全部”所有的“焦点”都在外。当对话框弹出时,条目失去焦点。这会导致tkinter在进行验证的过程中尝试进行另一轮验证。这可能会触发验证关闭,因为您可能会进入一个无法回避的循环。

        3
  •  2
  •   TheLizzard    3 年前

    不是最好的解决方案,但很有效:

    import tkinter as tk
    from tkinter import messagebox
    
    class MainWindow(tk.Tk):
        """ The main window
        """
        def __init__(self):
            tk.Tk.__init__(self)
            self.configure_window()
    
    
        def configure_window(self):
            """ Configure the main window
            """
            self.geometry("600x400")
            self.title("Testing entry validate command")
            self.bind_all("<Control-w>", lambda e: self.destroy())
            vcmd = (self.register(self.validate_input))
            entry1 = tk.Entry(self)
            entry1.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
            entry1.bind("<Key>", self.validate_input)
    
        def validate_input(self, event):
            """ Validate that the input only contains digits
            """
            if (event.state & 4) >> 2 == 1:
                # Ctrl+<event.keysym> was pressed
                if event.keysym == "c":
                    # Ctrl+c pressed
                    return None
                if event.keysym == "x":
                    # Ctrl+x pressed
                    return "break"
                if event.keysym == "v":
                    # Ctrl+v pressed
                    return "break"
            if not (event.char.isdigit() or event.char == ""):
                messagebox.showwarning(
                    "Alert", "Please enter a positive integer")
                return "break"
    
    
    def main():
        window = MainWindow()
        window.mainloop()
    
    main()
    

    "break" 从事件中,该事件被阻止且未被处理。