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

Good Monks, I can't help thinking that the solution to this problem must be well known but while I've studied the Perl/Tk book and searched the Web I can't get this working. I'm writing a program with Perl/Tk where the relevant bits are like this:
my $mw = MainWindow->new(); $mw->protocol(WM_DELETE_WINDOW=>\&exitfile); my $menuframe = $mw->Frame(-bd=>4, -relief=>'groove')->pack(-side=>'to +p', -fill=>'x', -expand=>'x');<br> my $canvasframe = $mw->Frame(-bd=>4, -relief=>'groove')->pack(-side=>' +bottom', -fill=>'both', -expand=>'both');
...
my $canvas1 = $canvasframe->Scrolled('Canvas', -width=>'20i', -height= +>'10i', -background=>$papercolour)->pack(-fill=>'both', -expand=>'bot +h'); $canvasframe->focus; $mw->bind($keypress=>\&$action); MainLoop;
where the keypresses and actions are read from a file (you can view the whole source of the main module at http://sandyfleming.org/swposter_0_3.txt if you want). This works excellently for all keys except the Tab key. Pressing the tab key causes the focus to change so that from then on keys such as the arrow keys move the canvas about instead of doing the action I've bound to them. What am I doing wrong?

Replies are listed 'Best First'.
Re: Tab Key in Perl/Tk
by Courage (Parson) on Feb 24, 2005 at 10:13 UTC
    Your latest line  $mw->bind($keypress=>\&$action); not reached until you exit your GUI, because MainLoop loops until you exit.

    Also use <code> tags to quote your program code.

    Best regards,
    Courage, the Cowardly Dog

      I've added the code tags - thanks for pointing that out.

      The line you complained about was in a subroutine in the actual code so it's OK. Sorry for not making that clear with my cut and paste.

Re: Tab Key in Perl/Tk
by wolfger (Deacon) on Feb 24, 2005 at 13:58 UTC

    I had the opposite problem a while back. I had a text field in which the tab key entered \t when I wanted it to shift focus. Simply using bind didn't work. Here is what I wound up doing:

    my $t1 = $mw->Text( -background=>"navy", -foreground=>"white", -height=>35, -width=>80, -wrap=>"word", -selectbackground=>"blueviolet" ); $t1->bindtags( [ ($t1->bindtags)[1,0,2,3] ] ); + # fix the bindtags order so that widget events are + # processed before class events $t1->bind("<Tab>", sub { $t1->focusNext; Tk->break; }); + #Fix tab to shift focus, not print a tab.

    Perhaps something similar is what you need.


    --
    Linux, sci-fi, and Nat Torkington, all at Penguicon 3.0
    perl -e 'print(map(chr,(0x4a,0x41,0x50,0x48,0xa)))'
      Thanks - I just wish I had your original problem because it seems to be the behaviour I want! I don't exactly understand your solution so I'll have to read up this. I think I've been too lucky with Perl/Tk so far - I've done a lot of stuff with no problems but I suppose it means I haven't had to look too hard at how things really work!

        Sorry. To explain my problem a bit better, I was binding Tab to the behaviour I desired, but I kept getting the undesired behaviour anyway. The bindtags line simply says "instead of checking bindings in the regular order (0,1,2,3), check them in the order that gives my binding precednece (1,0,2,3). (as the comment says, "so widget events are processed before class events")
        Of course, it's possible that the other reply to your post (bind prior to MainLoop) will be all you need. I was just tossing this out there in case that didn't solve your problem.


        --
        Linux, sci-fi, and Nat Torkington, all at Penguicon 3.0
        perl -e 'print(map(chr,(0x4a,0x41,0x50,0x48,0xa)))'