http://www.perlmonks.org?node_id=624410

strat has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

when I use -validate with Tk::Entry, I get unexpected behaviour in combination with -textvariable and changing the variable. For this example, I used a button to change the variable $entryText which should succeed until the value of 3 and fail for bigger values.

#! /usr/bin/perl use warnings; use strict; use Tk; my $entryText = 1; print "Perl-Version: $]\nTk-Version: $Tk::VERSION\n"; my $mw = MainWindow->new(); my $entry = $mw->Entry( -textvariable => \$entryText, -validate => 'all', -validatecommand => \&ValidateCmd, ) ->pack( -side => 'left' ); $mw->Button( -text => 'increase', -command => sub { $entryText++ }, ) ->pack( -side => 'right' ); MainLoop; sub ValidateCmd { my( $newValue ) = @_; { local $" = '] ['; no warnings 'uninitialized'; print "ARGS: [@_]\n"; } # return error if value > 3 and don't change the content if( $newValue > 3 ) { print "Error: Too big: $newValue\n"; return 0; } # if return 1; } # ValidateCmd

With Perl 5.008008 and Tk 804.024:

Perl-Version: 5.008003 Tk-Version: 800.024 ARGS: [1] [] [] [-1] [-1] ARGS: [2] [] [1] [-1] [-1] ARGS: [3] [] [2] [-1] [-1] ARGS: [4] [] [3] [-1] [-1] Error: Too big: 4 ARGS: [4] [] [3] [-1] [-1] Error: Too big: 4 ARGS: [4] [] [3] [-1] [-1] Error: Too big: 4

everything works fine, but with Perl-Versions >= 5.008008 and Tk Version 800.027 the validation stops when the first 0 is returned and so bigger values than 3 can be inserted via $entryText:

Perl-Version: 5.008008 Tk-Version: 804.027 ARGS: [1] [] [] [-1] [6] ARGS: [2] [] [1] [-1] [6] ARGS: [3] [] [2] [-1] [6] ARGS: [4] [] [3] [-1] [6] Error: Too big: 4

and the variable may become bigger than 3 since the validation stops. Additionally, the interface of validatecommand is changed (-1 vs. 6 for the same type of action which could break a lot of existing apps).

From perldoc Tk::Entry:

The validateCommand will turn itself off by setting validate to none when an error occurs, for example when the validateCommand or invalidCommand encounters an error in its script while evaluating, or validateCommand does not return a valid boolean value.

But returning 0 (or undef or nothing) is no error in my eyes.

Is this a bug, or am I the bug?

Best regards,
perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Replies are listed 'Best First'.
Re: Bug: Tk::Entry 804.027 validate?
by graff (Chancellor) on Jul 02, 2007 at 11:52 UTC
    I have Tk 804.027 on Perl 5.8.6 (macosx) and it behaves the same as your 804.027 -- i.e. not as advertised. I was struck by the value "6" in the last argument passed to the validation sub. According to the docs, this arg is supposed to be:
    * type of action. 1 == INSERT, 0 == DELETE, -1 if it's a forced validation or textvariable validation
    That by itself is something I'd call a bug. I also tried setting the "invalidCommand" option on Tk::Entry, to invoke a sub that resets the variable when it goes above 3 (and prints a warning), but that didn't seem to affect the behavior at all (and the sub passed as the "invalidCommand" parameter apparently never ran -- no warning was printed, the textvariable was not reset).
Re: Bug: Tk::Entry 804.027 validate?
by zentara (Archbishop) on Jul 02, 2007 at 13:27 UTC
    <2 cents> First of all, my immediate reaction is that using validate with textvariable, is asking for trouble..... but your point about existing scripts breaking is valid.

    Validate is intended for inspecting the value of something entered into the Entry widget. Some tidbits from the perldoc:

    The characters to be added (or deleted). This will be "undef" if validation is due to focus, explcit call to validate or if change is due to "-textvariable" changing.

    So you have undef values poping in there, when textvariable change occurs.

    In general, the textVariable and validateCommand can be dangerous to mix. If you try set the textVariable to something that the validateCommand will not accept it will be set back to the value of the entry widget. Using the textVariable for readonly purposes will never cause problems.

    So my advice is to redesign your script, to check for values in another way, rather than relying on the validate callback.

    Why design something to use something which may go undef? You could just as easily put the value-check in the button callback( or wherever you set $entryText ).

    If you really want to pursue this, you should probably ask on comp.lang.perl.tk. where one of the Tk internals experts may know something. </2cents>


    I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      Hello zentara,

      The reason why I want to do it that way is Tk::EntryCheck. This module that allows you to control which chars may be entered and up to which lenght into a Tk::Entry widget. I wrote this module because I prefer preventing invalid or too many chars to letting the user insert everything and then checking it and rising errors and the like.

      Well, I now try to rewrite this module using Tie::Watch.

      Best regards,
      perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

        Hi, the mention of Tie::Watch, triggered my memories of Tk::Trace( which may work better with Tk). It's only glitch, is that you need to pre-declare package Tk and add Tk::Trace. See Simple Tk Gauge

        I'm not really a human, but I play one on earth. Cogito ergo sum a bum