原文:
10.8. How do I configure a Scrollbar to scroll multiple widgets?
Note that the widget type that you wish to scroll can be important as a scroll "unit" on a Text or Listbox may be a character (several pixels - depending on font) whereas it would be an X "units" on a Canvas (could be pixel - but you may also specify other units).
A concrete answer for scrolling 3 Listboxes comes courtesy of Frederick L. Wagner <derf@ti.com>:
From a working example of multi-xscrolling:
sub multiscrollx { # multiscrollx my ($sb,$wigs,@args) = @ARG; my $w; foreach $w (@$wigs) { $w->xview(@args); } } # multiscrollx # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $sh->configure( -command => [ \&multiscrollx, $sh, [$scratchrule,$ruleheader,$ruletable]]); $ruletable->configure( -xscrollcommand => [ 'set', $sh]); $ruleheader->configure( -xscrollcommand => [ 'set', $sh]); $scratchrule->configure(-xscrollcommand => [ 'set', $sh]);In this case,
$sh is a horizontal Scrollbar,
$ruletable and $scratchrule are Tables
$ruleheader is an Entry
However, this approach is good for any widget with X-scrolling capability, I think. So the Y counterpart should be:
sub multiscrolly { # multiscrolly my ($sb,$wigs,@args) = @ARG; my $w; foreach $w (@$wigs) { $w->yview(@args); } } # multiscrolly # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $sv->configure( -command => [ \&multiscrolly, $sv, [$l1,$l2,$l3]]); $l1->configure( -yscrollcommand => [ 'set', $sv]); $l2->configure( -yscrollcommand => [ 'set', $sv]); $l3->configure( -yscrollcommand => [ 'set', $sv]);
Hope that helps.
Greg VanSickle mailto:vansickl@bnr.ca points out that this little script snippet does not provide for the binding of '<Button-2<' that he is accustomed to. He wrote a package called DSListbox to address this binding issue.
Conversely, Jong Park asked how to setup multiple Scrollbars to scroll the same widget. Nick Ing-Simmon's reply makes use of an anonymous sub and can be summed up in a little script that scrolls a Text widget (to see the scrolling in action type more than 20 lines of text into the widget):
#!/usr/local/bin/perl -w use Tk; my $mw = MainWindow->new(); my $s1 = $mw->Scrollbar(-orient => 'vertical'); my $s2 = $mw->Scrollbar(-orient => 'vertical'); $s1->pack(-side => 'left', -fill => 'y'); my $t = $mw->Text( -yscrollcommand => sub{$s1->set(@_), $s2->set(@_)}, -wrap => 'word', -width => 70, -height => 20, -font => $font, -setgrid => 1, )->pack(-side => 'left'); $s2->pack(-side => 'right', -fill => 'y'); $s1->configure(-command => [$t => 'yview']); $s2->configure(-command => [$t => 'yview']); MainLoop; __END__
译文:
10.8. 如何配置用一个滚动条来控制多个组件?
首先,值得注意的是,对于Text或Listbox等组件而言,滚动的“单位”可能是一个字符的(相当于十几个或几十个象素——这取决于字体的大小),而对于像Canvas这样的组件而言则就是一个象素(当然你也可以指定其它的单位)。因此,当你在考虑要用一个滚动条来同时控制多个组件的时候,可能需要考虑一下组件的类型。
尊敬的Frederick L. Wagner先生提供了一个同时滚动三个组件的具体例子:
(取自一个实际的多组件横行滚动的例子)
sub multiscrollx
{ # multiscrollx
my ($sb,$wigs,@args) = @_;
my $w;
foreach $w (@$wigs)
{
$w->xview(@args);
}
} # multiscrollx
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$sh->configure( -command => [ \&multiscrollx, $sh,
[$scratchrule,$ruleheader,$ruletable]]);
$ruletable->configure( -xscrollcommand => [ 'set', $sh]);
$ruleheader->configure( -xscrollcommand => [ 'set', $sh]);
$scratchrule->configure(-xscrollcommand => [ 'set', $sh]);
在这个例子中,$sh是一个横向的滚动条,$ruletable和$scratchrule都是Table,而$ruleheader是一个输入框。
但是,这个例子只是对于需要横向滚动的组件而言的。因此,我想与之相应的纵向滚动应该是这样的:
sub multiscrolly
{ # multiscrolly
my ($sb,$wigs,@args) = @_;
my $w;
foreach $w (@$wigs)
{
$w->yview(@args);
}
} # multiscrolly
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$sv->configure( -command => [ \&multiscrolly, $sv,
[$l1,$l2,$l3]]);
$l1->configure( -yscrollcommand => [ 'set', $sv]);
$l2->configure( -yscrollcommand => [ 'set', $sv]);
$l3->configure( -yscrollcommand => [ 'set', $sv]);
希望这些会对大家有所帮助。
Greg VanSickle指出这小段脚本没有提供对于其惯用的’<Button-2>’的绑定。为此,他写了一个叫DSListbox的包来实现这个绑定。
另外,相反的是Jong Park却询问起如何设置用多个滚动条来控制同一个组件的问题。Nick Ing-Simmon的回答是使用一个匿名的子程序。下面就是一个用这种方法来控制一个Text组件的例子(要看到滚动的效果,请在文本框中输入超过20行的文字):
#!/usr/local/bin/perl -w
use Tk;
my $mw = MainWindow->new();
my $s1 = $mw->Scrollbar(-orient => 'vertical');
my $s2 = $mw->Scrollbar(-orient => 'vertical');
$s1->pack(-side => 'left', -fill => 'y');
my $t = $mw->Text(
-yscrollcommand => sub{$s1->set(@_), $s2->set(@_)},
-wrap => 'word',
-width => 70,
-height => 20,
-setgrid => 1,
)->pack(-side => 'left');
$s2->pack(-side => 'right', -fill => 'y');
$s1->configure(-command => [$t => 'yview']);
$s2->configure(-command => [$t => 'yview']);
MainLoop;
__END__