A Validating Entry Widget
June 30, 1998 | Fredrik Lundh
This module implements a validating version of the Tkinter Entry widget. It uses the textvariable option to attach a StringVar variable to the widget, and uses the variable trace function to keep track of what’s going on. To specify how validation is to be done, override the validate method.
Note that the constructor takes a parent widget, and also allows you to use the value option to specify the initial contents. All other options are passed on to the Entry widget itself.
from Tkinter import * class ValidatingEntry(Entry): # base class for validating entry widgets def __init__(self, master, value="", **kw): apply(Entry.__init__, (self, master), kw) self.__value = value self.__variable = StringVar() self.__variable.set(value) self.__variable.trace("w", self.__callback) self.config(textvariable=self.__variable) def __callback(self, *dummy): value = self.__variable.get() newvalue = self.validate(value) if newvalue is None: self.__variable.set(self.__value) elif newvalue != value: self.__value = newvalue self.__variable.set(self.newvalue) else: self.__value = value def validate(self, value): # override: return value, new value, or None if invalid return value
Note: Newer versions of Tkinter support validate and validatecommand options that can be used instead of the extra variable. The above code still works, though.
Examples #
The first two examples are subclasses that check that the input is a valid Python integer or float, respectively. The validate method simply tries to convert the value to an object of the right kind, and returns None (reject) if that fails.
class IntegerEntry(ValidatingEntry): def validate(self, value): try: if value: v = int(value) return value except ValueError: return None
class FloatEntry(ValidatingEntry): def validate(self, value): try: if value: v = float(value) return value except ValueError: return None
The third example is a subclass that restricts the length of the input to a given max length.
class MaxLengthEntry(ValidatingEntry): def __init__(self, master, value="", maxlength=None, **kw): self.maxlength = maxlength apply(ValidatingEntry.__init__, (self, master), kw) def validate(self, value): if self.maxlength is None or len(value) <= self.maxlength: return value return None # new value too long
Here’s how to use this class:
root = Tk() entry = MaxLengthEntry(root, maxlength=20) entry.pack() mainloop()
Note that if the user pastes a long string into the entry box, it will be rejected by this implementation. A better solution might be to change the validate method to:
def validate(self, value):
if self.maxlength:
value = value[:self.maxlength]
return valueTODO: describe validate arguments and possible return values, and add more examples.
