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

Hello

I have the following code governing the TAB behavior. TAB should switch the focus between the first two Entry fields. This works fine. What I do not like is that if the Entry 3 gets the focus, and I click on TAB, Tk fires an error (which is expected). How can I "clean" the code and prevent this error? If I am in Entry 3 and press TAB, the focus should simply stay in this Entry field, or go to one of the other two fields (and start moving between the two fields if TAB is hit again). My code:

use strict; use warnings; use Tk; my $mw = MainWindow->new(); my $entry1 = $mw->Entry()->pack(); my $entry2 = $mw->Entry()->pack(); my $entry3 = $mw->Entry()->pack(); my %after = ($entry1 => $entry2, $entry2 => $entry1, ); $mw -> bind('all','<Tab>',sub{ ($after{$_[0]})->focus; } ); $mw->MainLoop(); exit(0);

My error:

Tk::Error: Can't call method "focus" on an undefined value at C:\Users +\FC\Desktop\Entry.pl line 14. <Key-Tab> (command bound to event)

Replies are listed 'Best First'.
Re: Perl/Tk binding Tab
by tybalt89 (Monsignor) on Oct 31, 2018 at 14:44 UTC
    #!/usr/bin/perl use strict; use warnings; use Tk; my $mw = MainWindow->new(); my $entry1 = $mw->Entry()->pack(); my $entry2 = $mw->Entry()->pack(); my $entry3 = $mw->Entry()->pack(); my %after = ($entry1 => $entry2, $entry2 => $entry1, ); $mw -> bind('all','<Tab>',sub{ ($after{$_[0]} // $_[0])->focus; } ); $mw->MainLoop(); exit(0);

      It works, thank you. Can you explain this. I am not sure I understand it: ($after{$_[0]} // $_[0])->focus;

        // is the defined-or operator. If the left part is undefined, take the right part else take the left part.

        my $c = $a // $b;

        Is like

        my $c = defined $a ? $a : $b;

        but easier and chainable

        my $x = $a // function ($b) // $ENV{FOO} // $self->bar // 0;

        Enjoy, Have FUN! H.Merijn
        Hi, it may help to know that the calling widget is the first argument $_[0] pass to any Tk callback. This code may show you what is happening. Notice how the Entry widget changes with each Tab.
        #!/usr/bin/perl use strict; use warnings; use Tk; my $mw = MainWindow->new(); my $entry1 = $mw->Entry()->pack(); my $entry2 = $mw->Entry()->pack(); my $entry3 = $mw->Entry()->pack(); my %after = ($entry1 => $entry2, $entry2 => $entry1, ); $mw -> bind('all','<Tab>',sub{ print "@_\n"; ($after{$_[0]} // $_[0])->focus; } ); $mw->MainLoop(); exit(0);

        I'm not really a human, but I play one on earth. ..... an animated JAPH