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

I have a program that has many Tk::Entry widgets on it. All of them require a value between 0.0 and 100.0.
I am validating the entries on 'focusout', and if the contents pass, I'm saving the value in a hash.
What I would like to be able to do is use the same validation routine for all of the entries. I'm having trouble figuring out how to save the value, though.
My version of perl is 5.6.1 built for sun4-solaris. I see in "Mastering Perl/Tk" that I should be able to call "$widget->focusLast" to find which entry just lost focus, but it's not in my Widget.pm.
Is there a way to send additional arguments to the Entry callback, beyond the 5 listed in Mastering Perl/Tk page 126?
Thanks.

Replies are listed 'Best First'.
Re: Generic Entry widget validation
by zentara (Cardinal) on Jun 03, 2005 at 19:44 UTC
    Here is a way. I have the validation set up to be between 0 and 100, as integer, but you can change the regex to include a . for real values.
    #!/usr/bin/perl use strict; use warnings; use Tk; my $top = MainWindow->new(); my %entries; for(1..4){ $entries{$_}{'value'} ||= 0; $entries{$_}{'entry'} = $top->Entry( -textvariable => \$entries{$_}{'value'}, -width => 5, -validate => 'key', -vcmd => \&validate, )->pack; } MainLoop; #have to make sure empty value has numeric context sub validate{ my $val = shift; $val ||= 0; #get alphas and punctuation out if( $val !~ /^\d+$/ ){ return 0 } if (($val >= 0) and ($val <= 100)) {return 1} else{ return 0 } }

    I'm not really a human, but I play one on earth. flash japh
Re: Generic Entry widget validation
by zentara (Cardinal) on Jun 03, 2005 at 21:10 UTC
    Just for the sake of it being a Friday afternoon, here is a version that only allows "real" numbers.
    #!/usr/bin/perl use strict; use warnings; use Tk; use Regexp::Common qw/number/; my $top = MainWindow->new(); $top->geometry('200x200'); my %entries; for(1..4){ $entries{$_}{'value'} ||= 0.0; $entries{$_}{'entry'} = $top->Entry( -textvariable => \$entries{$_}{'value'}, -width => 15, -validate => 'key', -vcmd => \&validate, )->pack; } MainLoop; #have to make sure empty value has numeric context sub validate{ my $val = shift; $val ||= 0.0; #get real numbers only #this regex allows 2 decimal points....bad # if( $val !~ /^[\d+\.]+$/ ){ return 0 } if( $val !~ /^$RE{num}{real}$/ ) { return 0 } if (($val >= 0.0) and ($val <= 100.0)) {return 1} else{ return 0 } }

    I'm not really a human, but I play one on earth. flash japh
Re: Generic Entry widget validation
by spurperl (Priest) on Jun 04, 2005 at 08:14 UTC
    It looks like you got a good answer from zentara, I just want to add regarding the last question in your post:

    Generally, there is a way to send arguments to Tk callbacks, for instance this example (from Mastering Tk):

    foreach my $key ( qw/0 1 2 3 4 5 6 7 8 9/ ) { $mw->bind( "<Key-$key>" => [\&key, $key] ); $mw->bind( "<KP_$key>" => [\&key, $key] ); }
    $key is an argument sent to the &key subroutine. Note that $key has a lexical binding, it is assigned when the foreach is executed.
Re: Generic Entry widget validation
by sfinster (Acolyte) on Jun 08, 2005 at 15:33 UTC
    Thanks zentara and spurperl, but I already know how to define callbacks and send arguments to them.

    The problem is that the Tk::Entry validation callback defines 5 arguments: proposed value, characters being added or deleted, current value, index in the string, and the action type. I don't know how to send it *additional* arguments of my own.

    I am also validating on 'focusout', not on 'key'. Once I have verified that the entry is ok, I want to save it into my object.

    If I define a separate callback for each Tk::Entry on the GUI, I know which part of my object's hash to update.

    My boss wants this finished "yesterday", so for now I'm going with separate callbacks. Voluminous and repetetive, yes, but it works. I will see if I can come up with a short code example to show my problem.

    By the way, I tried validating on 'key' and discovered a different problem. If a value changes I want to enable the 'Save' item on my pulldown menu, and I couldn't get that to work.