代码之家  ›  专栏  ›  技术社区  ›  Alexander Korovin

交互验证tkinter中的条目小部件内容(第2部分-更改条目对象的属性)

  •  0
  • Alexander Korovin  · 技术社区  · 7 年前

    Interactively validating Entry widget content in tkinter

    我想通过检查输入类型来更改背景色。很遗憾,我无法将条目指针传递给验证函数: vcmd = (self.register(self.onValidate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')

        self.entry = tk.Entry(self, validate="all")
        self.entry['validatecommand'] = self.onValidate2(self.entry)
    

    但这只起作用一次。请您解释一下,访问验证函数(或其他函数)的对象的最佳方式是什么,以及为什么我的 validatecommand

    以下是上面链接中的完整代码,其中有一些更正:

    import tkinter as tk  # python 3.x
    # import Tkinter as tk # python 2.x
    
    class Example(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
    
            # valid percent substitutions (from the Tk entry man page)
            # note: you only have to register the ones you need; this
            # example registers them all for illustrative purposes
            #
            # %d = Type of action (1=insert, 0=delete, -1 for others)
            # %i = index of char string to be inserted/deleted, or -1
            # %P = value of the entry if the edit is allowed
            # %s = value of entry prior to editing
            # %S = the text string being inserted or deleted, if any
            # %v = the type of validation that is currently set
            # %V = the type of validation that triggered the callback
            #      (key, focusin, focusout, forced)
            # %W = the tk name of the widget
    
            vcmd = (self.register(self.onValidate),
                    '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
     #       self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
            self.entry = tk.Entry(self, validate="all")
    #        self.entry['validatecommand'] = vcmd
            self.entry['validatecommand'] = self.onValidate2(self.entry)
            self.text = tk.Text(self, height=10, width=40)
            self.entry.pack(side="top", fill="x")
            self.text.pack(side="bottom", fill="both", expand=True)
    
    def onValidate(self, d, i, P, s, S, v, V, W):
            self.text.delete("1.0", "end")
            self.text.insert("end","OnValidate:\n")
            self.text.insert("end","d='%s'\n" % d)
            self.text.insert("end","i='%s'\n" % i)
            self.text.insert("end","P='%s'\n" % P)
            self.text.insert("end","s='%s'\n" % s)
            self.text.insert("end","S='%s'\n" % S)
            self.text.insert("end","v='%s'\n" % v)
            self.text.insert("end","V='%s'\n" % V)
            self.text.insert("end","W='%s'\n" % W)
            self.text.insert("end","W='%s'\n" % W)
            W.config({"background": "Red"})
    
            # Disallow anything but lowercase letters
            if S == S.lower():
                return True
            else:
                self.bell()
                return False
    
    
        def onValidate2(self, entry):
            try:
                entry.config({"background": "White"})
                value = int(entry.get())
                print("Int Value=",value)
    #                return int(value)
            except ValueError:
                entry.config({"background": "Red"})
    
    if __name__ == "__main__":
        root = tk.Tk()
        Example(root).pack(fill="both", expand=True)
        root.mainloop()
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Bryan Oakley    7 年前

    我无法将条目指针传递给验证函数

    nametowidget 方法将该名称转换为小部件的实例。

    你能解释一下吗。。。为什么我的validatecommand只使用一次?

    self.entry['validatecommand'] = self.onValidate2(self.entry)
    

    上述代码在功能上与此相同:

    result = self.onValidate2(self.entry)
    self.entry['validatecommand'] = result
    

    立即 validatecommand None . 这个 validationcommand 选项必须设置为 可调用 .


    下面是一个你正在努力实现的工作示例。通常,validate命令必须返回 True 对于有效条目和 False 对于无效条目,但我猜您实际上希望允许无效条目,而只是希望将背景变成红色。

    本例创建了多条目小部件,通过将小部件的名称传递给验证函数,您可以看到单个验证函数适用于多个小部件。

    import tkinter as tk
    
    class Example(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
    
            vcmd = self.register(self.onValidate)
    
            for i in range(4):
                entry = tk.Entry(self, validate="all")
                entry.configure(validatecommand=(vcmd, "%W", "%P"))
                entry.pack(side="top", fill="x")
    
        def onValidate(self, entry_name, new_value):
            entry = self.nametowidget(entry_name)
            entry.configure(background="white")
            try:
                int(new_value)
            except ValueError:
                entry.configure(background="red")
            return True
    
    if __name__ == "__main__":
        root = tk.Tk()
        Example(root).pack(fill="both", expand=True)
        root.mainloop()