There were a number of bugs in your sample code which I've cleaned up in the code below. It's generally a good idea not to use global variables if you can avoid it, and generally you can. It's also a good idea to use Perl style for loops when you can rather than C style, and again generally you can.
use strict;
use warnings;
use Tk;
use Tk::Table;
use Tk::Entry;
use Tk::Label;
use constant kRows => 3;
use constant kCols => 3;
main (); # Use a main sub to ensure that there are no global variables
+s
sub main {
my $mw = new MainWindow;
$mw->Label (
-text => "Enter any character",
-foreground => "red",
-font => "verdanafont 10 bold"
)->pack (-side => "top");
my $table_frame = $mw->Frame ()->pack (-padx => "10");
my $table = $table_frame->Table (
-columns => kCols,
-rows => kRows,
-scrollbars => "o",
-fixedrows => 1,
-fixedcolumns => 1,
-relief => 'raised',
-pady => "20",
-takefocus => "0"
);
my $press = $mw->Button (
-text => "Press Me",
-command => [\&PressMe, $mw, $table], # pass parameters into c
+allback
-font => "verdanafont 10 bold",
-state => 'disabled',
)->pack (
-side => "left",
-padx => "5",
-ipadx => "5"
);
my $filled = 0;
for my $col (0 .. kCols - 1) {
my $tmp_label = $table_frame->Label (-text => "$col")->pack ()
+;
$table->put (0, $col, $tmp_label);
}
for my $row (0 .. kRows - 1) {
for my $col (0 .. kCols - 1) {
my $ent1 = $table->Entry (
-font => "verdana 10",
-validate => 'key',
# Pass button widget and a ref to $filled into callbac
+k. Need a
# ref because we manipulate $filled in the callback
-vcmd => [\&onEdit, $press, \$filled],
)->pack (-ipady => "15");
$table->put ($row, $col, $ent1);
}
}
$table->pack ();
MainLoop;
}
sub onEdit {
my ($button, $filled, $new, $edit, $current, $idx, $type) = @_;
return 1 if $new eq $current;
if (length $new && !length $current) {
++$$filled;
} elsif (!length $new && length $current) {
--$$filled;
}
if ($$filled == kRows * kCols) {
$button->configure (-state => 'normal');
} else {
$button->configure (-state => 'disabled');
}
return 1;
}
sub PressMe {
my ($mw, $table) = @_;
my $message = "alphanumeric entered";
Outer: for my $row (0 .. kRows - 1) {
for my $col (0 .. kCols - 1) {
my $name = $table->get ($row, $col);
my $val = $name->get ();
next if $val =~ m/^[a-z0-9]+$/i;
$message =
"Bad entry ($val) in row "
. ($row + 1)
. ", column "
. ($col + 1);
last Outer;
}
}
my $response = $mw->messageBox (
-type => "ok",
-message => $message,
-icon => "info",
-title => "info!!"
);
}
Note the array technique used to pass extra parameters into the call back routines. The extra parameters are passed before the normal parameters.
Note too the use of named constants to provide row and column counts rather than relying on using the correct manifest constants everywhere (four places for each in this small sample script!). Also note that the column and row indexes range from 0 to count - 1: easier to see and get right with the Perl for loops using the range operator than with the C style for loops.
I also reworked your validation checking in the button call back so that the message box is only shown once and only for the first bad cell value found. You could of course check all the cells and report all the errors found by not terminating the loop early and by concatenating error messages together.
Perl reduces RSI - it saves typing
|