I have a small Tk gui that uses Tk::Entry input to get a MAC. I got most of the code from an old thread here. It works great, but I found a weird bug:
When I put invalid text into a field that represents a MAC octet (e.g. "zz"), and then try to leave the field (via Tab key or mouse-click), it properly forces me back into the field with the errant entry.
The problem is, if I hit the Tab key twice in quick succession, it will pop me out of the bad field, and what's more (worse), will seem to "forget" about the field, as you will see if you run the code.
To replicate, enter "zz" in a field, double-hit Tab quickly, then hit Tab regularly to hop thru the other (blank) fields. When you come back around to the "zz" field, it won't run the validation check again - no matter if the bad string is removed/replaced, etc.
#!/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,$_ ], -invalidcommand => [ \&show_invalid,$entries{$_}{'entry'} ], ); $entries{$_}{'entry'}->pack(-side => 'left'); } 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) = @_; $widget->focus(); # temporarily flash the background of the problem field in red my $bg = $widget->cget('-bg'); $widget->configure(-bg => 'red'); $widget->update(); # effect a sleep of 200 milliseconds select(undef,undef,undef,0.2); # return the background color to the original state $widget->configure(-bg => $bg); $widget->update(); }
Edit: If you can't replicate the problem using the Tab key, it also seems to happen if you pre-populate a field's textvariable with an invalid string.
For example, inserting this line into the loop will make the 3rd field fail initial validation, but will allow focus to pass thru it without subsequently attempting validation:
for(1..6){ $entries{$_}{'addy'} = 'zz'.$_ if($_ == 3);
In reply to Tk::Entry and double-Tab key weirdness by atreyu
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |