Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^2: Tk::Entry and double-Tab key weirdness

by atreyu (Sexton)
on May 25, 2012 at 19:43 UTC ( [id://972525]=note: print w/replies, xml ) Need Help??


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

@zentara,

First of all, thanks for pointing that out - you are absolutely right (no shocker there), removing that sleep fixes the double-Tab issue. Why am I using it? B/c that is what the code I borrowed had. Why did the original code have it? I believe to give it that flashing red background effect...something I can (and will) live without.

However, the issue is still there if a textvariable is pre-defined with a bad string (as I noted in the update to my OP). This is more important than the other issue, b/c this will definitely crop up. The textvariable may or may not be pre-defined before displaying the widget, but if it is, and it is invalid, I would like validation to work.

Any idea what is going on there?

Edit: seems to work if I first create the widgets, then go back and configure them:

for(1..6){ $entries{$_}{'entry'} = $fr->Entry(); $entries{$_}{'entry'}->configure( -textvariable => \$entries{$_}{'addy'}, -width => 3, # -validate => 'focusout', # -validatecommand => [ \&validate,$_,\%entries ], # -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'},$_ ], ); $entries{$_}{'entry'}->pack(-side => 'left'); } for(1..6){ $entries{$_}{'addy'} = 'zz'.$_ if($_ == 3); $entries{$_}{'entry'}->configure( -validate => 'focusout', -validatecommand => [ \&validate,$_,\%entries ], -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'},$_ ], ); }

Replies are listed 'Best First'.
Re^3: Tk::Entry and double-Tab key weirdness
by zentara (Archbishop) on May 26, 2012 at 11:12 UTC
    This might help you. It changes color, but dosn't flash. Also it helps to use 'any' for the validate method, rather than focusout. The key lines are
    $mw->waitVisibility; $mw->after(100,sub{$entries{3}{'entry'}->focusForce});
    Here is a working script that should show you the way of highlighting a textvariable which is invalid. You can perfect it yourself. :-)
    #!/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'); my %entries; for(1..6){ $entries{$_}{'entry'} = $fr->Entry(); $entries{$_}{'entry'}->configure( -textvariable => \$entries{$_}{'addy'}, -width => 3, # -validate => 'focusout', # -validatecommand => [ \&validate,$_,\%entries ], # -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'},$_ ], ); $entries{$_}{'entry'}->pack(-side => 'left'); } for(1..6){ $entries{$_}{'addy'} = 'zz'.$_ if($_ == 3); $entries{$_}{'entry'}->configure( #-validate => 'focusout', -validate => 'all', -validatecommand => [ \&validate,$_,\%entries ], -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'},$_ ], ); } $mw->waitVisibility; $mw->after(100,sub{$entries{3}{'entry'}->focusForce}); MainLoop(); # 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"; return $valid; } sub show_invalid { my($widget) = @_; # print "@_\n"; $widget->focus(); # background of the problem field in red my $bg = $widget->cget('-bg'); $widget->configure(-bg => 'lightpink'); $widget->update(); }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      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'); } }
        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
Re^3: Tk::Entry and double-Tab key weirdness
by Anonymous Monk on May 26, 2012 at 08:02 UTC
    For all sleeping in tk apps gui frameworks use tk that gui framework timer functions, use Tk::after
Re^3: Tk::Entry and double-Tab key weirdness
by Khen1950fx (Canon) on May 25, 2012 at 20:25 UTC

    ...that is what the code I borrowed had..

    The road to Hell is paved with borrowed code:-).
      The road to Hell is paved with borrowed code:-).

      Then I'm building the Devil an 8-lane superhighway...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://972525]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2024-04-18 13:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found