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.
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.
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.
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.
Perhaps the only thing the callback needs to know is what
text currently appears in the Entry
. If
that is the case, it can use the .get()
method of the textvariable
associated with
the widget to retrieve that text.
In this case, all you need is the option “validatecommand=
”, where f
is the name of your callback function.
f
Tkinter can also provide a number of items of information
to the callback. If you would like to use some of these
items, when you call the Entry
constructor,
use the option validatecommand=(
, where f
, s1
, s2
, ...)
is the name of your callback
function, and each additional f
is a
substitution code. For each substitution code that you
provide, the callback will receive a positional argument
containing the appropriate value.
si
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.