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

When I use an entry widget in Perl/Tkx, the behavior is not what I expect. Here is sample code:
use strict; use Tkx; Tkx::package_require("tile"); Tkx::package_require("style"); my $mw = Tkx::widget->new("."); my $text = "abc"; my $entry = $mw->new_ttk__entry(-width => 20, -textvariable => \$text) +; $entry->configure(-font => "helvetica 14 bold"); $entry->g_grid(-column => 0, -row => 0, -sticky => 'w'); $entry->configure(-validate => 'all', -validatecommand => \&Entry); Tkx::MainLoop(); sub Entry { ### Tkx::update(); print "text = '$text'\n"; return 1; }
When I run the script and click in the entry widget, I get text = 'abc' printed, which is what I expect. When I then type '1' in the entry widget, I still get text = 'abc' printed, but I expected to get text = 'abc1'. When I then type '2', I get text = 'abc1', but I expected to see text = 'abc12'. When I click outside of the widget, the correct string is then printed. Is there a way to have the validatecommand get the current value of the textvariable? I've tried changing the -validate value from "all" to other values, but that doesn't help. I've tried adding a call to Tkx::update() (see commented out code), but that doesn't seem to have any affect. Any help would be appreciated.

Thanks,
Dave

Replies are listed 'Best First'.
Re: Perl/Tkx Entry widget problem
by jethro (Monsignor) on Jan 10, 2011 at 17:05 UTC

    From the docs:

    The validateCommand and invalidCommand are called with the following arguments:

    * The proposed value of the entry. If you are configuring the entry widget to have a new textvariable, this will be the value of that textvariable.

    * The characters to be added (or deleted). This will be undef if validation is due to focus, explcit call to validate or if change is due to -textvariable changing.

    * The current value of entry i.e. before the proposed change.

    * index of char string to be added/deleted, if any. -1 otherwise

    * type of action. 1 == INSERT, 0 == DELETE, -1 if it's a forced validation or textvariable validation

    When you validate in your sub, the variabel $text is still unchanged, because the new value isn't validated yet. You can observe proposed changes in the parameters to your Entry function and you should return 0 or 1 depending on your validation result.

      I got some help elsewhere for this. Needed to read (and understand) the ttk::entry manual page. Using a Tkx::Ev event in the -validatecommand is new to me.

      Here is a revised script that prints out all the information described in the ttk::entry man page. The $P parameter is the one I'm interested in.

      use strict; use Tkx; Tkx::package_require("tile"); Tkx::package_require("style"); my $mw = Tkx::widget->new("."); my $text = "abc"; my $entry = $mw->new_ttk__entry(-width => 20, -textvariable => \$text) +; $entry->configure(-font => "helvetica 14 bold"); $entry->g_grid(-column => 0, -row => 0, -sticky => 'w'); # $entry->configure(-validate => 'all', -validatecommand => \&Entry); $entry->configure(-validate => 'all', -validatecommand => \&Entry); # $entry->configure(-validatecommand => [\&Entry, Tkx::Ev('%P'), $entr +y]); #$entry->configure(-validatecommand => [\&Entry, Tkx::Ev('%d', '%i', ' +%P', '%s', '%S', '%v', '%V', '%W'), $entry]); $entry->configure(-validatecommand => [\&Entry, Tkx::Ev('%d', '%i', '% +P', '%s', '%S', '%v', '%V', '%W'), $entry]); Tkx::MainLoop(); sub Entry { my ($d, $i, $P, $s, $S, $v, $V, $W) = @_; print "action = '$d'\n"; print "index = '$i'\n"; print "new value = '$P'\n"; print "current value = '$s'\n"; print "insert string = '$S'\n"; print "validate option = '$v'\n"; print "validation trigger = '$V'\n"; print "widget name = '$W'\n"; return 1; }

      David