in reply to Re^3: Tk::Entry and double-Tab key weirdness
in thread Tk::Entry and double-Tab key weirdness

Here is a working script that should show you the way of highlighting a textvariable which is invalid.

@zentara,

Thanks for this, will definitely check it out!

heh, lightpink should not be too hard to miss...

Edit:

zentara, I checked out your code, there are a couple problems. The first is; I think in your validate sub, you left off the 2nd argument ($ref), b/c in yours it is trying to validate a HASH, not the value in the field. Am I right there?

The second is; if I use 'all' instead of 'focusout' for -validate, then it breaks again - I can tab or click out of the bad field. Is there some other piece missing for 'all' to work properly?

Edit 2:

Here's an updated version that I'm now trying out. It seems to work okay. It incorporates zentara's suggestion of using 'all' vs 'focusout' (though I'm not sure how/why it is working correctly...)

Also, to get it to evaluate all pre-populated fields when the app first fires up, I'm using eventGenerate to auto-Tab thru all the fields. It will stop on the first bad field it encounters, by virtue of the fact that I disable all other Entry widgets, if a problem is discovered. Once the field is validated, the other fields are re-enabled.

This works, but it feels very hacky though...(the auto-tabbing and widget-disabling parts).

#!/usr/bin/perl use strict; use warnings; use Tk; my $mw = MainWindow->new(-title => 'Mac Address Input Example'); my $fr = $mw->Frame()->pack(-expand => 1, -fill => 'both'); my $lb = $fr->Label(-text => 'MAC Address')->pack(-side => 'left'); # widget used to display Entry field errors my $errW = $fr->Label(-foreground=>'red')->pack(-side=>'bottom'); # hash to hold Entry widgets my %entries; # loop thru the number of Entry widgets desired for(1..6){ # create the Entry widget $entries{$_}{'entry'} = $fr->Entry( -textvariable => \$entries{$_}{'addy'}, -width => 3, ); # save default widget background $entries{$_}{'bg'} = $entries{$_}{'entry'}->cget('-bg'); # pack/display the widget $entries{$_}{'entry'}->pack(-side => 'left'); } # loop back thru the created widgets for(1..6){ # put some bogus values in for testing... $entries{$_}{'addy'} = ($_>1) ? $_.$_ : ''; $entries{$_}{'addy'} .= 'z' if($_ == 3 or $_ == 4); # configure the validation for the widget $entries{$_}{'entry'}->configure( # -validate => 'focusout', -validate => 'all', -validatecommand => [ \&validate,$_ ], -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'},$_ ], ); } # put focus on initial Entry widget $entries{1}{'entry'}->focus(); # auto-tab thru all Entry widgets to perform validation on pre-populat +ed values for(1..6){ $mw->eventGenerate('<Tab>'); # $mw->idletasks; $mw->after(100); $mw->update; } MainLoop(); sub clear_err { my($num) = @_; $errW->configure(-text=>''); $entries{$num}{'entry'}->configure(-bg=>$entries{$num}{'bg'}); } # returns `1' if valid, and `0' if invalid sub validate { my($num,$val) = @_; unless($val){ print "Field $num has nothing to validate\n";return 1; +} my $valid = ($val =~ /^[0-9a-f]{1,2}$/i) ? 1 : 0; printf "Field %s, validating \`%s'...%s\n",$num,$val,$valid? "ok": " +FAILED"; if($valid){ # clear error widget &clear_err($num); # re-enable all other widgets for(1..6){ next if(/^$num$/); $entries{$_}{'entry'}->configure(-state=>'normal'); } }else{ # update the error widget with text indicating a problem with the +value $errW->configure(-text=>"Field $num value \`$val' is invalid"); } return $valid; } sub show_invalid { my($widget,$num) = @_; $widget->focus(); # turn the background of the problem field to red my $bg = $widget->cget('-bg'); $widget->configure(-bg => 'red'); $widget->update(); # temporarily disable focus on all other widgets for(1..6){ next if(/^$num$/); $entries{$_}{'entry'}->configure(-state=>'disabled'); } }

Replies are listed 'Best First'.
Re^5: Tk::Entry and double-Tab key weirdness
by zentara (Cardinal) on May 29, 2012 at 20:28 UTC
    I checked out your code, there are a couple problems.

    I said, I showed you the way, and it was up to you to perfect it. :-) It looks like you did a nice job. By the way, Entry validation is notoriously hard to setup right, you are doing a pretty good job.

    P.S. I would enlarge the font and make a white background color if I were you.

    # fontcreate works more reliably to add a font $mw->fontCreate('big', # -family=>'arial', -weight=>'bold', -size=> 18 ); # create the Entry widget $entries{$_}{'entry'} = $fr->Entry( -font => 'big', -textvariable => \$entries{$_}{'addy'}, -width => 3, -bg => 'white' );

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      I said, I showed you the way, and it was up to you to perfect it. :-)

      i am spoiled, zentara. i have copied more of your code examples than I can remember and it had always works flawlessly before... ;)

      I would enlarge the font and make a white background color if I were you.

      Good suggestion - my "final product" code has the white background in the fields, but thanks for noting. i've used fontCreate before, but I'm lazy and use the -font => '{arial} 18 {bold}' syntax a lot. Could you tell me what the difference is there, if there is one (other than you can re-use 'big' as a font in your code, which is ultimately easier)?

        Could you tell me what the difference is there,

        The -font => '{arial} 18 {bold}' syntax seems pretty clean, but from my experience, setting the font with fontCreate always resulted in fewer glitches. I'm an old timer, and started Tk when you needed to specify fonts with stuff like:

        -font => '-Adobe-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*';
        Yuck!. Also see Tk Font Manipulation. When you use fontCreate to create the font, you can more easily manipulate them later.

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh