The ValidateEntry widget, described on Fredrik Lundh's page on Validating Entry Widget, can be used to confirm that the value that the user enters is what you, the programmer, wanted. Fredrik's example code doesn't show you how to retrieve the data entered by the user (use a StringVar called self.results), but the example below does. If you want to use the widget as a module that you import, you'll have to do a little more work.

Another approach to entry validation is provided in Chapter 6 of Grayson's book on Tkinter. His example 6-17 spells out the details.

   1 '''
   2 Info by Fredrik Lundh:
   3 This module implements a validating version of the Tkinter Entry widget.
   4 It uses the textvariable option to attach a StringVar to the widget,
   5 and uses the variable trace function to keep track of what's going on (in real time, as the user types the input).
   6 To specify how validation is to be done, override the validate method.
   7 Note that the constructor takes a parent widget, and also allows you to use the value option to specify the initial contents.
   8 All other options are passed on to the Entry widget itself.
   9 '''
  10 
  11 from Tkinter import *
  12 
  13 class ValidatingEntry(Entry):
  14     # base class for validating entry widgets
  15 
  16     def __init__(self, master, value="", **kw):
  17         Entry.__init__(self, master, **kw)
  18         self.__value = value
  19         self.__variable = StringVar()
  20         self.__variable.set(value)
  21         self.__variable.trace("w", self.__callback)
  22         self.config(textvariable=self.__variable)
  23         self.results = StringVar()
  24         if self.__value is None: self.results.set(None)
  25         else:
  26                 self.results.set(self.__value)
  27 
  28     def __callback(self, *dummy):
  29         value = self.__variable.get()
  30         newvalue = self.validate(value)
  31         if newvalue is None:
  32             self.__variable.set(self.__value)
  33         elif newvalue != value:
  34             self.__value = newvalue
  35             self.__variable.set(newvalue)
  36         else:
  37             self.__value = value
  38 
  39     def validate(self, value):
  40         # override: return value, new value, or None if invalid
  41         self.results.set(value)
  42         return value
  43 
  44     def getresults(self, value):
  45         # override: return value, or chopped value in the case of ChopLengthEntry
  46         return self.results.get()
  47 
  48 '''
  49 The first two examples are subclasses that check that the input is a valid Python integer or float, respectively.
  50 The validate method simply tries to convert the value to an object of the right kind, and returns None (reject) if that fails.
  51 '''
  52 
  53 class IntegerEntry(ValidatingEntry):
  54     def validate(self, value):
  55         try:
  56             if value:
  57                 v = int(value)
  58                 self.results.set(value)
  59             return value
  60         except ValueError:
  61             return None
  62 
  63 
  64 class FloatEntry(ValidatingEntry):
  65     def validate(self, value):
  66         try:
  67             if value:
  68                 v = float(value)
  69                 self.results.set(value)
  70             return value
  71         except ValueError:
  72             return None
  73 
  74 
  75 class MaxLengthEntry(ValidatingEntry):
  76     '''MaxLength is a subclass that restricts the length of the input to a given max length.
  77        The getresults method is provided only to deal with a situation where a too-long
  78        initial value is provided, and the user accepts it without editing.
  79        Also if a too-long initial value is provided, it must be truncated to at least one char
  80        less than the max length, or else the user will be unable to even edit it
  81        (since the Del or BS key would cause the length to exceed the maxlength, they would be ignored)'''
  82     def __init__(self, master, value="", maxlength=None, **kw):
  83         if len(value) > maxlength-1:
  84                 value = value[:maxlength-1]
  85         self.maxlength = maxlength
  86         ValidatingEntry.__init__(self, master, value=value)
  87 
  88     def validate(self, value):
  89         if self.maxlength is None or len(value) <= self.maxlength:
  90                 self.results.set(value)
  91                 return value
  92         return None # new value too long
  93 
  94     def getresults(self, value):
  95         if self.maxlength:
  96                 if len(value) > self.maxlength:
  97                         value = value[:self.maxlength]
  98                         self.results.set(value)
  99         return self.results.get()
 100 
 101 class ChopLengthEntry(ValidatingEntry):
 102     '''ChopLengthEntry accepts all entries, but chops them when the results are called for'''
 103     def __init__(self, master, value="", maxlength=None, **kw):
 104         self.maxlength = maxlength
 105         ValidatingEntry.__init__(self, master, value=value)
 106 
 107     def getresults(self, value):
 108         if self.maxlength:
 109                 if len(value) > self.maxlength:
 110                         value = value[:self.maxlength]
 111                         self.results.set(value)
 112         return self.results.get()
 113 
 114 
 115 class StringEntry(ValidatingEntry):
 116         #same as ValidatingEntry; nothing extra
 117         pass
 118 
 119 if __name__ == '__main__':
 120         labelString = ['Integer','Float','String','MaxLength','ChopLength']
 121         limitString = ['MaxLength','ChopLength']
 122         initial     = [123, 456.789, '"hello, world!"', '"long text"', '"Please don\'t cut me!"']
 123         num = len(labelString)
 124 
 125         entry = [None]*num; value = [None]*num
 126 
 127         def results():
 128                 resultsList = []
 129                 for i in range(num):
 130                         value[i] = entry[i].results.get()
 131                         value[i] = entry[i].getresults(value[i])
 132                         if value[i] is not None:
 133                                 resultsList.append( value[i] )
 134                 for x,y in zip(labelString, resultsList):
 135                         print "validated %s entry is: %s" % (x, y)
 136                 root.destroy()
 137 
 138         root = Tk()
 139         lab = []; but = []; entry = []
 140         #if we put the names of the various widget into a list, we can create instances
 141         #  using a for loop. Note that we need to handle
 142         #  the special case that 2 of them have a 2nd argument, while the others don't
 143         # (alternatively, could have re-defined the widgets to all take a (sometimes unneeded) 2nd argument)
 144         for i in range(num):
 145                 but.append(None)
 146                 lab.append(Label(text = 'please enter a '+labelString[i]))
 147                 lab[-1].pack(side='top')
 148                 if labelString[i] in limitString:
 149                         entry.append(eval(labelString[i] + 'Entry')(root, value=initial[i], maxlength=10))
 150                 else:
 151                         entry.append(eval(labelString[i] + 'Entry')(root, value=initial[i]))
 152                 entry[-1].pack()
 153 
 154         bt = Button(text = 'Ok', command = results)
 155         bt.pack(side='left')
 156         cn = Button(text = 'Cancel', command = root.destroy)
 157         cn.pack(side='left')
 158         mainloop()
 159 

Screenshot:

tkValidatingEntry2.png

tkinter: ValidateEntry (last edited 2010-07-26 11:59:11 by localhost)