Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: Tk bind key scrolled Text

by jcb (Parson)
on Sep 15, 2019 at 23:41 UTC ( [id://11106216]=note: print w/replies, xml ) Need Help??


in reply to Tk bind key scrolled Text

I have had similar problems, except that I usually wanted to allow tabs to be inserted into the Text widget.

Interestingly, Shift-<Tab> still reverses the sequence according to Tk's builtin order, including to get out of a Text widget.

The most elegant solution would be to adjust the stacking order so that Tk's builtin focus order matches what you want, see "focusNext" in Tk::focus and "raise" in Tk::Widget. This approach also preserves the "tab-in" behavior of focusing the first widget when the user presses <Tab> and no widget has the focus within the window.

Finding a solution to this, producing <Tab> key behavior not unlike that in the browser I am using to compose this reply, required some time with the Tk manual and was quite enlightening along the way. I recommend installing Tk::Pod if you do not already have it — tkpod makes navigating the sprawling Tk manual easy. In the below code, I have also added a binding that exits the program upon typing Control-Q for convenience in testing and initialized the Text widget to contain a dump of its own bindings, which revealed a class binding for <Tab> that inserts a tab character. This is overridden on line 17 to instead do nothing, allowing the default global binding for focusNext to work. Removing the binding also works, but leaves the default InsertKeypress binding to run, which inserts a tab, then the global binding changes focus. Maddening at first...

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 $text = $mw->Scrolled('Text')->pack(); my @order = ($entry1 , $entry3, $entry2, $text); for (my $i = 1; $i < @order; $i++) { $order[$i]->raise($order[$i-1]) } $mw->bind('<Control-q>', sub {exit 0}); $text->Subwidget('xscrollbar')->configure(-takefocus => 0); $text->Subwidget('yscrollbar')->configure(-takefocus => 0); $text->Subwidget('scrolled')->bind('Tk::Text','<Tab>', 'NoOp'); $text->insert('1.0', join('',$text->Subwidget('scrolled')->bindDump)); $mw->MainLoop(); exit(0);

Dumping the default bindings also reveals that <Control-Tab> executes focusNext even on a Tk::Text widget.

Replies are listed 'Best First'.
Re^2: Tk bind key scrolled Text
by Takamoto (Monk) on Sep 16, 2019 at 06:19 UTC

    Thank you very much for your example, which works very good! A limitation it seems to have is that - different to my approach - you can not 'leave out' some widget from this behavior. If you use the following in your code:

    my @order = ($entry1 , $entry3, $text);

    where $entry2 simply needs to be jumped, it does not work, i.e. it does not jump it. So, perfect solution if you want to use all widgets displayed, but not if you want just a set of widget to be affected.

      You can leave out $entry2 by using $entry2->configure(-takefocus => 0); to omit $entry2 from the tabbing order, like my example did for the scrollbars. An Entry widget with -takefocus => 0 will still get the focus if the user clicks on it, however.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11106216]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 09:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found