Thread Tk::Text verliert den Fokus (10 answers)
Opened by PerlProfi at 2007-04-03 16:01

ptk
 2007-04-05 14:30
#46280 #46280
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
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:

Code: (dl )
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:

Code: (dl )
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:

Code: (dl )
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__

View full thread Tk::Text verliert den Fokus