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.

 
File: tkValidatingEntry.py
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 value

TODO: describe validate arguments and possible return values, and add more examples.

 

A Django site. rendered by a django application. hosted by webfaction.