Search code examples
tkintertkinter-entry

OnValidate - registering lots of different validations


I wrote a GUI tool which has a lot of variables that can be changed via entrys. Every entry has a different validation rule and I only show around 20 items per page (array of entries). I fear that when I register too many validations (on TK) without unregistering (?) before switching to the next page my program will crash sooner or later because it stacks? If yes, how can I unregister?

def is_ascii(s):
  try:
    s.decode('ascii')
  except (UnicodeDecodeError,UnicodeEncodeError) :
      return False          
  else:
      return True          

def OnValidate2(i,P,S,char=0,signed=0,bits=0):
  if char:
    if int(i)==0 :
      return is_ascii(S)
    else: return False
  elif signed:
    pass # more to follow

vcmd2 = (root.register(OnValidate2),'%i', '%P','%S',1)
ent = Entry(root, validate="key", validatecommand=vcmd2)  #unregister ??

Solution

  • Don't worry about it. There is no need to unregister a validation function. Bear in mind you only need to define and register a given function once. Once OnValidate2 has been registered, you can use it with as many widgets as you want.

    It seems rather odd to have dozens of different validation functions. You might want to consider combining several into a general purpose routine. For example, if you have one that checks for one bit and one that checks for two, you can have a single function that works for either.

    Here's an example showing how you register a single command and use it with several different parameters:

    import Tkinter as tk
    
    class Example(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
            cmd = root.register(self._validate)
    
            row = 0
            self.grid_columnconfigure(1, weight=1)
            for char in (0,1):
                for signed in (0,1):
                    for bits in (0,1,2,3,4,5,6,7):
                        txt = "char: %s signed: %s bits: %2s:" % (char, signed, bits)
                        vcmd = (cmd, "%i", "%P", "%S", char, signed, bits)
                        label = tk.Label(self, text=txt)
                        entry = tk.Entry(self, validate="key", validatecommand=vcmd)
                        label.grid(row=row, column=0)
                        entry.grid(row=row, column=1, sticky="ew")
                        row += 1
    
        def _validate(self, i,P,S, char=0, signed=0, bits=0):
            print "validating char=", char, "signed=", signed, "bits=", bits,
            print "P=", P, "i=", i, "S=", S
            return True
    
    
    if __name__ == "__main__":
        root = tk.Tk()
        Example(root).pack(fill="both", expand=True)
        root.mainloop()