in reply to Tk: Binding Keys to events

Hi tamaguchi,

Note that you don't have to pass the subroutine as an anonymous subroutine within a list reference.

That is to say, although it will work to do:

$mw->bind( '<Control-KeyPress-a>', [sub {print "Button a has been pr +essed\n"}] ); $mw->bind( '<Control-KeyRelease-a>', [sub {print "Button a has been re +leased\n"}] );

One often specifies either a simple anonymous subroutine:

$mw->bind( '<Control-KeyPress-a>', sub {print "Button a has been pre +ssed\n"} ); $mw->bind( '<Control-KeyRelease-a>', sub {print "Button a has been rel +eased\n"} );

or a simple anonymous list:

$mw->bind( '<Control-KeyPress-a>', [ \&say_button_pressed, "a" ]); $mw->bind( '<Control-KeyRelease-a>', [ \&say_button_released, "a" ]); # Unlikely to do it this way unless the following subroutines are # longer, or likely to be called from multiple places... # sub say_button_pressed { printf "Button %s has been pressed\n", $_[0]; } sub say_button_released { printf "Button %s has been released\n", $_[0]; }

I tend to use the former, an anonymous subroutine, when the code is brief and simple, whereas the latter is better when the subroutine is long and complex.


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

Replies are listed 'Best First'.
Re^2: Tk: Binding Keys to events
by tamaguchi (Pilgrim) on Oct 03, 2006 at 10:43 UTC
    Thank you all. What is the rationale for having the syntax '<Control-KeyPress-a>' wouldn´t be more clear to write <KeyPress-Control-a>'?
      It might well be more clear, but it doesn't work:
      #!/usr/bin/perl -w + use Tk; + use strict; use warnings; + my $mw = new MainWindow(); $mw->bind( '<KeyPress-Control-a>', sub {print "Button a has been press +ed\n"} ); $mw->bind( '<KeyPress-Control-a>', sub {print "Button a has been relea +sed\n"} ); MainLoop; # Produces ... bad event type or keysym "Control" at /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/Tk/Derived.pm l +ine 469. # My version of Perl This is perl, v5.8.0 built for i386-linux-thread-multi

      s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
        Hi tamaguchi,

        No, there's no way to do it using multiple keypresses (that I'm aware of).  And even if you could, there would be a problem when you held the 2 keys down, and relied on key repeats; whichever key you pressed "last" will dictate the direction that the object moves in.

        You can try it yourself by holding down the left and up arrow, for example; the initial movement might appear to be a "wobbly" northwest movement, but after the repeat kicks in, the square will only move left or up.

        My recommendation would be to assign a completely different set of keys.  For example, you could use the 8 keys centered around the "k":

        my $pbindings = { 'Key-j' => sub { $c->move($rect, -5, 0) }, 'Key-l' => sub { $c->move($rect, 5, 0) }, 'Key-i' => sub { $c->move($rect, 0, -5) }, 'comma' => sub { $c->move($rect, 0, 5) }, 'Key-u' => sub { $c->move($rect, -5, -5) }, 'Key-o' => sub { $c->move($rect, 5, -5) }, 'Key-m' => sub { $c->move($rect, -5, 5) }, 'period' => sub { $c->move($rect, 5, 5) }, }; + map { $mw->bind("<$_>" => $pbindings->{$_}) } (keys %$pbindings);

        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
        This program creates a yellow rectangle on a canvas. The rectangle is possible to move up, down, left, and right by the respective arrow keys.
        #!/usr/bin/perl -w use Tk; use strict; my $mw = MainWindow->new; my $c = $mw->Scrolled('Canvas', -width => 200, -height => 200, -background =>'blue', -scrollregion => [ 0, 0, 500, 500 ] ); $c->pack(-expand => 1, -fill => 'both'); my $rect=$c->createRectangle(100, 100, 150, 150, -fill => 'yellow'); + $mw->bind('<KeyPress-Left>', sub{$c->move($rect, -5, 0);}); $mw->bind('<KeyPress-Right>', sub{$c->move($rect, 5, 0);}); $mw->bind('<KeyPress-Up>', sub{$c->move($rect, 0, -5);}); $mw->bind('<KeyPress-Down>', sub{$c->move($rect, 0, 5);}); my @coords_list = $c->coords($rect); MainLoop;
        Now I would like to be able to move the rectangle on the diagonal by pressing for example both up and right. To write:
        $mw->bind('<Right-KeyPress-Up>', sub{$c->move($rect, 5, -5);});
        ..is however not possible do you have any other suggestions how to bind two arrowkeys to an event?