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

I'm trying to define a binding for keyboard events for a simple Tk::Frame. My sample program simply does not work. Button-Events work fine, but 'Key' or 'KeyPress' events are not dispatched to the callback.

Here is the code sample:

use Tk;

my $main = new MainWindow;
my $f = $main->Frame(-width => 100, -height => 100)->pack;
$f->bind('<Key>' => [sub {print "Key: $_1\n";}, Ev('K')]);
MainLoop;

This one is supposed to echo the keys pressed "in the widget" to the console. Why doesn't it work?

Cheers, Phil

Replies are listed 'Best First'.
Re: Key bindings for Tk::Frame?
by zentara (Cardinal) on Feb 03, 2010 at 16:45 UTC
    Maybe someone knows a better answer, but my understanding is that the Frame is a no frill container widget, and dosn't have the builtin internal bindings to respond to keys. Focus is the important concept, read "perldoc Tk::focus". Usually one binds to the $mw (toplevel) and sets the focus order of the widgets it holds.

    This first script shows the simplicity of the frame, notice no @_ is passed thru

    #!/usr/bin/perl use Tk; my $main = new MainWindow; my $f = $main->Frame(-width => 100, -height => 100)->pack; $f->bind('<Key>' => sub {print "Key: @_\n"} ); $f->bind('<Enter>' => sub { print "enter @_\n" } ); $f->bind('<Leave>' => sub { print "leave @_\n" } ); $f->focus; MainLoop;
    and here is a way around the problem
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; my $f = $mw->Frame(-width => 100, -height => 100)->pack; #$mw->bind( '<KeyPress>' => \&print_keysym ); $f->bind( '<KeyPress>' => \&print_keysym ); $mw->Button( -text => 'Exit', -command => sub { exit(); } )->pack; #button gets the default window focus, so we need # to give it to the frame $f->focus; # won't work without this MainLoop; sub print_keysym { my $widget = shift; my $e = $widget->XEvent; my ( $keysym_text, $keysym_decimal ) = ( $e->K, $e->N ); print "keysym=$keysym_text, numberic=$keysym_decimal\n"; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
      I'll be doggoned! - I "missed the focus" ;)

      With the

      $f->focus;
      

      in place, everything works nicely!

      Btw., the "@_" is passed properly if you use callback syntax in the call to "bind", i.e.:
      $f->bind('<Key>' => [sub {print "Key: $_1\n";}, Ev('K')]);
      
      Cheers, Phil