【问题标题】:How to validate tkinter entry [duplicate]如何验证 tkinter 条目 [重复]
【发布时间】:2021-03-27 14:59:41
【问题描述】:

我正在开发一个 tkinter 应用程序,该应用程序具有一个条目小部件和一个在用户在其中输入内容时验证它的方法。问题是 绑定在 self.entry_str 更新之前运行 validate 方法,因此它测试条目中以前的内容。我想要它做的是在self.entry_str 更新后运行验证方法,有人知道我该怎么做吗?这是简化的程序:

import sys
import tkinter as tk


class GUI:
    def __init__(self, master):
        # frame
        self.frame = tk.Frame(master)
        self.frame.pack()
        # StringVars
        self.error = tk.StringVar()
        self.error.set('')
        self.entry_str = tk.StringVar()
        self.entry_str.set('')
        # widgets
        self.entry = tk.Entry(self.frame, textvariable=self.entry_str)
        self.entry.bind('<Key>', lambda _: self.validate_entry())
        self.entry.grid(row=0, column=0)
        self.error_label = tk.Label(self.frame, textvariable=self.error, fg='red')
        self.error_label.grid(row=1, column=0)
        self.bttn = tk.Button(self.frame, text='continue', command=sys.exit)
        self.bttn.grid(row=2, column=0)

    def validate_entry(self):
        try:
            _ = int(self.entry_str.get())
        except ValueError:# entry is not valid: disable button and show error
            self.error.set('entry has to be an integer')
            self.bttn.config(state='disabled')
        else:# entry is valid: enable button and hide error
            self.error.set('')
            self.bttn.config(state='normal')


root = tk.Tk()
gui = GUI(root)
root.wm_title('entry validation test')
root.mainloop()

【问题讨论】:

    标签: python python-3.x tkinter tkinter-entry


    【解决方案1】:

    使用&lt;KeyRelease&gt; 而不是&lt;Key&gt;

    更好的方法是使用.trace

    self.entry_str = tk.StringVar()
    self.entry_str.set('')
    self.entry_str.trace('w', self.validate_entry)
    
    ...
    
    def validate_entry(self, *event):
            try:
                _ = int(self.entry_str.get())
             ...
    

    另一种方法是禁止用户输入除整数以外的任何内容。

    self.entry = tk.Entry(self.frame, textvariable=self.entry_str, validate='key', validatecommand=(master.register(self.validate), "%P"))
    ...
    def validate(self, char):  # this function must return only True or False
            return char.isdigit() or char==''
    
    

    请注意self.entry_str 将始终是最新的

    【讨论】:

    • 第二种方法如何处理 Ctrl+V 事件?
    • @TheLizzard 除非剪贴板中没有数字,否则粘贴操作会正常工作
    【解决方案2】:

    您有 2 个选项。第一个:在用户输入数据之前保存入口数据,如果需要,可以像这样恢复数据:

    import sys
    import tkinter as tk
    
    
    class GUI:
        def __init__(self, master):
            # frame
            self.frame = tk.Frame(master)
            self.frame.pack()
            # StringVars
            self.error = tk.StringVar()
            self.error.set('')
            self.entry_str = tk.StringVar()
            self.entry_str.set('')
            # widgets
            self.entry = tk.Entry(self.frame, textvariable=self.entry_str)
            self.entry.bind('<Key>', self.validate_entry)
            self.entry.grid(row=0, column=0)
            self.error_label = tk.Label(self.frame, textvariable=self.error, fg='red')
            self.error_label.grid(row=1, column=0)
            self.bttn = tk.Button(self.frame, text='continue', command=sys.exit)
            self.bttn.grid(row=2, column=0)
    
            self.current_entry_state = ""
            self.error_occured = False
    
        def validate_entry(self, event):
            current_entry_state = self.entry_str.get()
            # Save the state only if there are no invalid characters:
            try:
                _ = int(self.entry_str.get())
                self.current_entry_state = current_entry_state
                self.error_occured = False
            except:
                self.error_occured = True
            # Wait for tkinter to display the character
            self.entry.after(1, self._validate_entry)
    
        def _validate_entry(self):
            try:
                _ = int(self.entry_str.get())
            except ValueError:# entry is not valid: disable button and show error
                self.error.set('entry has to be an integer')
                # Restore the entry's text:
                self.entry.delete("0", "end")
                self.entry.insert("end", self.current_entry_state)
            else:
                if not self.error_occured:# entry is valid: enable button and hide error
                    self.error.set('')
    
    
    root = tk.Tk()
    gui = GUI(root)
    root.wm_title('entry validation test')
    root.mainloop()
    

    还有另一种方法(没有很好地记录),但请查看 this 和 this。

    【讨论】:

      猜你喜欢
      • 2018-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多