[Python-Help] data entry validation with Tkinter

Alex Martelli aleaxit at yahoo.com
Tue Aug 7 10:44:39 EDT 2001


"Ken Guest" <kwg at renre-europe.com> writes:
    ...
> attempts at specifying python procedures for vcmd and invcmd only seem
> to be called when the app in initialising and don't exactly work.

If you call a function (or other callable), it will indeed be called; so:

> For example, with
> 
> self.__entry = Entry(newframe, validate='key', vcmd=self.validate('%P'),
> invcmd=self.invalid())

this immediately calls self.validate and self.invalid, because their
mention is followed by parentheses '()' with arguments in between.  Then
arguments vcmd and invcmd are set to the RESULTS of these calls.

What you need to do is, set the argument to a CALLABLE (an object that
can be called, such as a function).  If you want self.invalid to be
called without arguments when invcmd 'happens', invcmd=self.invalid
will work just fine.  It's a little bit more work when you want to
pre-specify some of the arguments to be passed to the callable you
want (technically called 'currying', in honor of the great mathematician
Haskell Curry: look for "currying" in the search engine of activestate's
"Python Cookbook" site, there's a couple useful general recipes about
it).  Some Python programmers like 'lambda' for that purpose.  Me, I
prefer to give a name to the functions I write, so I'd write a little
local function definition and then pass that local function -- in
Python 2.2, that's:
    def validate(whatever):
        return self.validate('%P', whatever)
    self.__entry = Entry(newframe, validate='key', vcmd=validate,
        invcmd = self.invalid)
In Python 2.1 it's slightly more work (unless you have a
    from __future__ import nested_scopes
at the start of your module), and in 2.0 or earlier you do need
the extra work anyway, because there was no support for nested
scopes (so from within the validate local function name 'self'
was not implicitly defined), e.g.:
    def validate(whatever, self=self):
        return self.validate('%P', whatever)
and the setting of self.__entry just as above.

This assumes that when vcmd 'happens' it will supply an argument
to the callable you set for it in the Entry(...) call (correct if
that isn't so -- I'm no Tkinter expert:-).  Another possibility,
since you ARE using a bound-method (self.validate) anyway, is to
hold the '%P' as part of self's state (self.pattern='%P', say)
and just use cmd=self.validate just as shown for invcmd.  That
wouldn't work well if you want to use self.validate to validate
many fields with different patterns, though (but you could have
a method per validation pattern, if there aren't too many).


Alex






More information about the Python-list mailing list