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

Greetings all,
I've struck a minor problem with perl/Tk's widget bind() procedure, mainly that it doesn't work as documented - as far as I can tell.

I'm using the latest Perl/Tk from CPAN, w/perl 5.6.1, and as well as reading the POD, I've got Advanced Perl Programming and am hovering over the Perl/Tk chapters.

My first task is to bind to keys, which works as so:

$MW->bind('<k>', \&CallbackSub);
However the Advanced Perl Programming documented use of Ev() does not work for me, ala:
$MW->bind('<Any-KeyPress>', [\&mysub, Ev('k')]);
This returns a HASH object, not the key pressed. By doing the following I can get a SCALAR to be returned - but am not sure how to interpret the scalar:
$MW->bind('<Any-KeyPress>', sub { &mysub(Ev('k')) });
The next thing thats eluding me is binding the arrow-keys. (What I was hoping Ev() would tell me was the arrow-key ASCII code that I could use to bind them). I figured I'd be smart and bind 8, 6, 4 and 2 and just let keep the NumLock on - but binding those numbers does NOT bind the numeric keypad number keys!

Who can enlighten me as to whats going on, and how I should go about doing my final object.

JP,
-- Alexander Widdlemouse undid his bellybutton and his bum dropped off --

Edit Masem 2002-02-19 - fixed tags to use CODE instead of font changes

Replies are listed 'Best First'.
Re: Keyboard input with Perl/Tk's -bind()
by rjray (Chaplain) on Feb 12, 2002 at 00:06 UTC

    To address the first part of the question: Tk handles the callbacks different, based on the type of reference the programmer provides. If the reference is a CODE references (your second, working version), it simply calls it with the object to which the callback is tied as the first argument. That object is a blessed hash reference, which is why you saw that in the first example, as well. But in your second example, you never used the arg-list of the callback, rather, you directly called a second routine with the Ev() as the argument. When the reference passed to bind() is an ARRAY reference, it treats the first element as the coderef to call, and the rest as extra arguments. It still passes the object as the first argument, however. That is why your first attempt yielded a hashref.

    You do want to use the first form, however. When Tk is building the argument list for the callback, it detects the presence of "Ev(x)" and evaluates them in the context of the current event before placing the values on the calling stack. Your closure might prevent this (I'm not 100% sure that it will, but I can't imagine Tk being able to pick apart the anon-sub). What your "mysub" needs to do is expect the first argument to be the object ref, and look to the second argument to be the key.

    As for the codes for the arrow keys and such, it isn't as simple as plain ASCII codes for a given key. The keyboard (and thus X) considers the keypad numbers separately from the row across the top. If and when both yield the same ASCII characters is a matter of the application-- generally when you are typing text, it's fine to have them both generate the appropriate ASCII value. But as keys, that have codes that are known as keysyms associated with them. Your X environment should have a utility called "xev" installed. When you run it, it just spews info on X events to stdout. Try it, and look at what gets output for the arrows and the keypad keys. You'll find that the keypad numbers have keysyms like "KP_0", "KP_5", etc.

    Welcome to the world of X and event-based programming!

    --rjray

      Greetings,
      Many thanks rjray and Vavoom. My questions are answered more than satisfactorily, and my code does precisely what its supposed to now.
      Hooray! :)

      JP,
      -- Alexander Widdlemouse undid his bellybutton and his bum dropped off --

Re: Keyboard input with Perl/Tk's -bind()
by Vavoom (Scribe) on Feb 12, 2002 at 00:17 UTC
    If you are just looking for the symbols to reference the keys, they are (at least in my world):
    KP_Up
    KP_Down
    KP_Left
    KP_Right

    If, on the other hand, you want to be able to find the key symbols yourself, you can use this code (originally from Mastering Perl/Tk Chapter 15):
    #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->bind('<KeyPress>' => \&print_keysym); $mw->Button( text => 'Exit', command => sub { exit(); } )->pack; 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"; }

    If I completely misunderstood the question, feel free to elaborate for a better response.

    Vavoom