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

Hello monks,

I never considered this behaviour that even if logical seems annoying, at least to me. If i have an Entry widged and I enter there a character that is bound to a callback, the callback is called.

Consider the following example:

#!/usr/bin/perl use warnings; use strict; use Tk; # use Tk::WidgetDump; # use Tk::ObjScanner; my $mw = MainWindow->new(); $mw->geometry("100x100"); $mw->Entry( -text => '',-width => 20)->pack(); $mw->bind('<KeyRelease-?>' => sub{print "A question mark was pressed!! +\n"} ); # $mw->WidgetDump(); MainLoop;

When you enter in the Entry widget a question mark the anonymous sub is called. This is a very undesired beahviour for an application with potentially many Entry widgets and potentially many keybindings.

I think I can workaround this putting all Entry in an array @all_text_entries and manually iterating over them to clear all bindings esplicitly set by my application. Even if possible this seems very boring and possibly not so easy to maintain.

Uncomment the Tk::WidgetDump Tk::ObjScanner imports and the $mw->WidgetDump(); to see a very useful dump of all stuffs and bindings too.

Ideas?

L*

PS: sorry for my english that becomes worst due to sleep privation. What i intended to says is: it is possible to disable a keybinding to run it's associated sub if the bound key is entered into an Entry widget?

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: Tk preventing a char in Entry widged to trigger a KeyBinding
by tybalt89 (Monsignor) on Oct 11, 2016 at 16:46 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1173709 use strict; use warnings; use Tk; # use Tk::WidgetDump; # use Tk::ObjScanner; my $mw = MainWindow->new(); $mw->geometry("100x100+799+336"); $mw->bind('<KeyRelease-question>' => sub{print "A question mark was pr +essed!!\n"} ); my $entry = $mw->Entry( -text => '',-width => 20)->pack(); $entry->bind('<Enter>' => sub { $mw->bind('<KeyRelease-question>' => s +ub {})}); $entry->bind('<Leave>' => sub { $mw->bind('<KeyRelease-question>' => sub{print "A question mark was pressed!!\n"})}); # $mw->WidgetDump(); MainLoop;

    You could also try with FocusIn and FocusOut, or some combination of the two types.

      It still prints the message when I press ? inside the entry. The following works for me, though:
      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new->geometry("100x100+799+336"); my $entry = $mw->Entry( -text => '', -width => 20 )->pack(); $entry->bind('<KeyRelease-question>' => sub { Tk->break }); $mw->bind( '<KeyRelease-question>' => sub { print "? was pressed!\n" + }); $mw->Entry->pack; MainLoop();

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        Thanks choroba,

        your example works correctly, or well, it works as I desire. But this imply to collect all entries as named instances, ie my $entry_first = $mw->Entry... my $entry_second = $mw->Entry

        It is too much work for me! maybe i'll try to bind all Tk::Entry class to Tk->break for all my defined bindings.

        I was not aware of the possibility to bind to an entire class, nor about Tk->break

        Incidentally my $mw = MainWindow->new->geometry("100x100+799+336"); gives me an undefined value at line 9. On my Tk version i needed a more verbose statement my $mw = MainWindow->new(); $mw->geometry("100x100+799+336");

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

        Interesting - it doesn't print the message for me when the cursor is in the entry field.

      You could also try with FocusIn and FocusOut, or some combination of the two types.

      Not needed, see Tk::bind#DESCRIPTION/Tk::bindtags or  perl -MTk -le " print tkinit->Entry->bindDump "

      Dont bind to keypress when you're wanting to bind to key, don't override "class" bindings when you're wanting to override an instance binding .. bindtags order and break

Re: Tk preventing a char in Entry widged to trigger a KeyBinding
by Anonymous Monk on Oct 11, 2016 at 11:19 UTC
Re: Tk preventing a char in Entry widged to trigger a KeyBinding
by Anonymous Monk on Oct 11, 2016 at 23:35 UTC

    Bind toplevel ($mw) to warn on Key-questionmark

    also bind so children of $mw of "tag" Tk::Entry break

    at first MainWindow has focus, then tab is hit so focus is on the buttons ... when entry has focus nothing is printed

    #!/usr/bin/perl -- use strict; use warnings; use Tk; my @t = ( -text => 'focus on me and press ?' ); my $mw = tkinit; $mw->Checkbutton( @t )->pack; $mw->Button( @t )->pack; $mw->Entry( @t )->pack; $mw->bind(q/<Key-?>/,sub{warn "$Tk::widget ? " }); $mw->bind(qw/Tk::Entry <Key-?>/,sub{Tk->break}); MainLoop; __END__ MainWindow=HASH(0xf1eeec) ? at - line 10. MainWindow=HASH(0xf1eeec) ? at - line 10. MainWindow=HASH(0xf1eeec) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Button=HASH(0xf42c0c) ? at - line 10. Tk::Button=HASH(0xf42c0c) ? at - line 10. Tk::Button=HASH(0xf42c0c) ? at - line 10. Tk::Button=HASH(0xf42c0c) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10. Tk::Checkbutton=HASH(0xf55164) ? at - line 10.
      Thanks to his Anonymousity and all other monks who spent some time to help me.

      I think the bind qw/Tk::Entry <Key-?>/,sub{Tk->break}); is the laziest solution.

      In the case of several TopLevel windows, bindings can be aggregated into a lookup table. Then foreach window any binding is bound to the window and removed for the Tk::Entry class.

      It is also useful to bind <Return> to give back the focus for all Tk::Entry widgets.

      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new(); $mw->geometry("200x100+0+0"); $mw->Entry( -text => '',-width => 20)->pack(); $mw->Checkbutton( -text => 'focus on me and press ? or !' )->pack; my $mwbis = $mw->Toplevel(); $mwbis->geometry("200x100+300+0"); $mwbis->Entry( -text => '',-width => 20)->pack(); $mwbis->Checkbutton( -text => 'focus on me and press ? or !' )->pack; # a lookup table for all global bindings my %bind_table = ( '<KeyRelease-?>' => sub{print "A question mark was pressed!!\n"}, '<KeyRelease-!>' => sub{print "A esclamation mark was pressed!!\n"} +, ); foreach my $window ($mw, $mwbis){ # assign bindings to all TopLevel foreach my $bind (keys %bind_table){ $window->bind($bind => $bind_table{$bind}); # remove bindings for all Tk::Entry in all windows $window->bind('Tk::Entry', $bind,sub{Tk->break}); } # bind Return to for Tk::Entry to give the focus to parent $window->bind('Tk::Entry','<Return>' => sub{$_[0]->parent->focus}) } MainLoop;

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.