Durch bindtags() wird festgelegt, in welcher Reihenfolge Key-/Maus-/...-Bindings zum Tragen kommen. In Perl/Tk ist die Reihenfolge typischerweise: Klassenbindings des Widgets, Bindings des Widgets selbst, Bindings des Toplevels, in dem sich das Widget befindet und schließlich globale Bindings ("all").
Mit
$text->bind hast du das Binding des Widgets geändert, das Klassenbinding besteht aber nach wie vor und wird vor deinem Binding gefeuert. Mit Hook::WrapSubs kann man, schön zeigen, dass zuerst ein anderes Widget den Focus bekommt, aber dann sofort das Text-Widget den Focus zurückbekommt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl
use strict;
use warnings 'all';
use Tk;
use Tk::Text;
use Hook::WrapSub qw(wrap_subs);
wrap_subs sub { warn "called focus with args @_" }, 'Tk::focus', sub {};
my $mw = tkinit;
my $text = $mw->Scrolled('Text' =>
-scrollbars => 'ose',
-background => 'white',
-wrap => 'none')
->pack(-fill => 'both',
-expand => 1);
$text -> focus();
$text -> bind('<Control-Tab>', sub { $text->focus();
$text->break;
});
MainLoop;
_ _ END _ _
called focus with args Tk::Text=HASH(0x82dbcb4) at /tmp/b.pl line 8.
called focus with args Tk::Scrollbar=HASH(0x839f6f4) at /tmp/b.pl line 8.
called focus with args Tk::Text=HASH(0x82dbcb4) at /tmp/b.pl line 8.
Eine Möglichkeit ist, die Binding-Reihenfolge mit bindtags zu ändern, so dass die Widget-Bindings zuerst kommen. Bei Scrolled-Widgets ist noch die Besonderheit, dass man explizit das gescrollte Widget angeben muss:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/perl
use strict;
use warnings 'all';
use Tk;
use Tk::Text;
use Hook::WrapSub qw(wrap_subs);
wrap_subs sub { warn "called focus with args @_" }, 'Tk::focus', sub {};
my $mw = tkinit;
my $text = $mw->Scrolled("Text",
-scrollbars => 'ose',
-background => 'white',
-wrap => 'none')
->pack(-fill => 'both',
-expand => 1);
$text -> focus();
# Ändern der bind-Reihenfolge
my @tags = $text->Subwidget("scrolled")->bindtags;
@tags[0,1]=@tags[1,0];
$text->Subwidget("scrolled")->bindtags([@tags]);
$text -> bind('<Control-Tab>', sub { $text->focus();
$text->break;
});
MainLoop;
__END__
called focus with args Tk::Text=HASH(0x82dcd14) at /tmp/a.pl line 8.
called focus with args Tk::Text=HASH(0x82dcd14) at /tmp/a.pl line 8.
called focus with args Tk::Text=HASH(0x82dcd14) at /tmp/a.pl line 8.
Man kann es auch OO-mäßig lösen. Eine eigene Text-Klasse erstellen, die von Tk::Text erbt, und dort die Klassenbindings ändern:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/perl
use strict;
use warnings 'all';
use Tk;
use Tk::Text;
{
package Tk::MyText;
use base qw(Tk::Text);
Construct Tk::Widget 'MyText';
sub ClassInit {
my($class,$mw) = @_;
$class->SUPER::ClassInit($mw);
$mw->bind($class, '<Control-Tab>', sub { Tk->break });
$class;
}
}
use Hook::WrapSub qw(wrap_subs);
wrap_subs sub { warn "called focus with args @_" }, 'Tk::focus', sub {};
my $mw = tkinit;
my $text = $mw->Scrolled('MyText',
-scrollbars => 'ose',
-background => 'white',
-wrap => 'none')
->pack(-fill => 'both',
-expand => 1);
$text -> focus();
MainLoop;
__END__