Next / Previous / Contents

10.2. Adding validation to an Entry widget

In some applications, you will want to check the contents of an Entry widget to make sure they are valid according to some rule that your application must enforce. You define what is valid by writing a callback function that checks the contents and signals whether it is valid or not.

Here is the procedure for setting up validation on a widget.

  1. Write a callback function that checks the text in the Entry and returns True if the text is valid, or False if not. If the callback returns False, the user's attempt to edit the text will be refused, and the text will be unchanged.

  2. Register the callback function. In this step, you will produce a Tcl wrapper around a Python function.

    Suppose your callback function is a function named isOkay. To register this function, use the universal widget method .register(isOkay). This method returns a character string that Tkinter can use to call your function.

  3. When you call the Entry constructor, use the validatecommand option in the Entry constructor to specify your callback, and use the validate option to specify when the callback will be called to validate the text in the callback. The values of these options are discussed in more detail below.

Here are the values of the validate option and what they mean.

'focus'

Validate whenever the Entry widget gets or loses focus (see Section 53, “Focus: routing keyboard input”).

'focusin'

Validate whenever the widget gets focus.

'focusout'

Validate whenever the widget loses focus.

'key'

Validate whenever any keystroke changes the widget's contents.

'all'

Validate in all the above situations.

'none'

Turn off validation. This is the default option value. Note that this is the string 'none', not the special Python value None.

The value of the validatecommand option depends on what arguments you would like your callback to receive.

Here are the substitution codes.

Table 18. Callback substitution codes

'%d' Action code: 0 for an attempted deletion, 1 for an attempted insertion, or -1 if the callback was called for focus in, focus out, or a change to the textvariable.
'%i' When the user attempts to insert or delete text, this argument will be the index of the beginning of the insertion or deletion. If the callback was due to focus in, focus out, or a change to the textvariable, the argument will be -1.
'%P' The value that the text will have if the change is allowed.
'%s' The text in the entry before the change.
'%S' If the call was due to an insertion or deletion, this argument will be the text being inserted or deleted.
'%v' The current value of the widget's validate option.
'%V' The reason for this callback: one of 'focusin', 'focusout', 'key', or 'forced' if the textvariable was changed.
'%W' The name of the widget.

Here is a small example. Suppose you want your callback to receive the '%d' to find out why it was called; '%i' to find out where the insertion or deletion would occur; and '%S' to find out what is to be inserted or deleted. Your method might look like this:

    def isOkay(self, why, where, what):
        ...

Next you use the universal .register() method to wrap this function. We assume that self is some widget.

    okayCommand = self.register(isOkay)

To set up this callback, you would use these two options in the Entry constructor:

    self.w = Entry(self, validate='all',
         validatecommand=(okayCommand, '%d', '%i', '%S'), ...)

Suppose that the Entry currently contains the string 'abcdefg', and the user selects 'cde' and then presses Backspace. This would result in a call isOkay(0, 2, 'cde'): 0 for deletion, 2 for the position before 'c', and 'cde' for the string to be deleted. If isOkay() returns True, the new text will be 'abfg'; if it returns False, the text will not change.

The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.