Perl + Tk:将 (Scrolled/Listbox) 小部件引用传递给子例程
Perl + Tk: pass a (Scrolled/Listbox) widget reference to a subroutine
我在将列表框引用从一个子例程传递到另一个子例程时遇到问题。最后我想做的是:在 BoxA 中的 selection 中找出 selected 项目的值是什么,并根据该值在 boxB 中找到 select someting。
#!/usr/bin/perl -w
use Tk;
use strict;
use warnings;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $button = $mw -> Button (-text=>"Push me", -command => \&buttonCall) -> pack;
sub callee{
my $boxARef = $_[0];
my $boxBRef = $_[1];
my $index = $boxARef -> curselection();
$boxBRef -> selectionSet($index);
}
sub buttonCall{
my $boxA = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$boxA -> insert('end', @arr);
my $boxB = $mw -> Listbox(-exportselection=>0, -selectmode => 'multiple') -> pack;
$boxB -> insert('end', @arr);
$boxA -> bind ('<<ListboxSelect>>' => [\&callee,$boxA,$boxB] );
}
MainLoop;
执行代码结果:
Tk::Error: Can't call method "selectionSet" on unblessed reference at ./stack-test.pl line 14.
<<ListboxSelect>>
(command bound to event)
我是 Perl 的新手,非常感谢任何参考资料方面的帮助。
对 buttonCall()
中创建的框的引用似乎有些奇怪。以下对我有用:
use strict;
use warnings;
use Tk;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $boxA;
my $boxB;
my $button = $mw -> Button (
-text=>"Push me",
-command => sub { buttonCall( $boxA, $boxB ) }
) -> pack;
sub callee{
my ( $boxARef, $boxBRef ) = @_;
my $index = $$boxARef -> curselection();
$$boxBRef -> selectionSet($index);
}
sub buttonCall{
my ( $boxARef, $boxBRef ) = @_;
if ( !defined $$boxARef ) {
$$boxARef = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$$boxARef -> insert('end', @arr);
$$boxBRef = $mw -> Listbox(
-exportselection=>0, -selectmode => 'multiple'
) -> pack;
$$boxBRef -> insert('end', @arr);
$$boxARef -> bind ('<<ListboxSelect>>' => sub { callee( $boxARef, $boxBRef) });
}
}
MainLoop;
有两个问题:
如果您使用 [coderef, arg, arg...]
形式指定 Tk 回调,将始终使用触发事件的小部件调用 coderef 作为第一个参数传递。那就是你的$_[0]
。您要传递的两个参数将以 $_[1]
和 $_[2]
.
结尾
您的变量 $boxA
和 $boxB
已经是引用,但您使用额外的 \
运算符传递它们。这意味着在尝试对它们调用 Tk 方法之前,您必须在回调子中取消引用它们。 - 或者在回调定义中删除 \
:
use Tk;
use strict;
use warnings;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $button = $mw -> Button (-text=>"Push me", -command => \&buttonCall) -> pack;
sub callee{
my $boxARef = $_[1];
my $boxBRef = $_[2];
my $index = $boxARef -> curselection();
$boxBRef -> selectionSet($index);
}
sub buttonCall{
my $boxA = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$boxA -> insert('end', @arr);
my $boxB = $mw -> Listbox(-exportselection=>0, -selectmode => 'multiple') -> pack;
$boxB -> insert('end', @arr);
$boxA -> bind ('<<ListboxSelect>>' => [\&callee,$boxA,$boxB] );
}
MainLoop;
我在将列表框引用从一个子例程传递到另一个子例程时遇到问题。最后我想做的是:在 BoxA 中的 selection 中找出 selected 项目的值是什么,并根据该值在 boxB 中找到 select someting。
#!/usr/bin/perl -w
use Tk;
use strict;
use warnings;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $button = $mw -> Button (-text=>"Push me", -command => \&buttonCall) -> pack;
sub callee{
my $boxARef = $_[0];
my $boxBRef = $_[1];
my $index = $boxARef -> curselection();
$boxBRef -> selectionSet($index);
}
sub buttonCall{
my $boxA = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$boxA -> insert('end', @arr);
my $boxB = $mw -> Listbox(-exportselection=>0, -selectmode => 'multiple') -> pack;
$boxB -> insert('end', @arr);
$boxA -> bind ('<<ListboxSelect>>' => [\&callee,$boxA,$boxB] );
}
MainLoop;
执行代码结果:
Tk::Error: Can't call method "selectionSet" on unblessed reference at ./stack-test.pl line 14.
<<ListboxSelect>>
(command bound to event)
我是 Perl 的新手,非常感谢任何参考资料方面的帮助。
对 buttonCall()
中创建的框的引用似乎有些奇怪。以下对我有用:
use strict;
use warnings;
use Tk;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $boxA;
my $boxB;
my $button = $mw -> Button (
-text=>"Push me",
-command => sub { buttonCall( $boxA, $boxB ) }
) -> pack;
sub callee{
my ( $boxARef, $boxBRef ) = @_;
my $index = $$boxARef -> curselection();
$$boxBRef -> selectionSet($index);
}
sub buttonCall{
my ( $boxARef, $boxBRef ) = @_;
if ( !defined $$boxARef ) {
$$boxARef = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$$boxARef -> insert('end', @arr);
$$boxBRef = $mw -> Listbox(
-exportselection=>0, -selectmode => 'multiple'
) -> pack;
$$boxBRef -> insert('end', @arr);
$$boxARef -> bind ('<<ListboxSelect>>' => sub { callee( $boxARef, $boxBRef) });
}
}
MainLoop;
有两个问题:
如果您使用 [coderef, arg, arg...]
形式指定 Tk 回调,将始终使用触发事件的小部件调用 coderef 作为第一个参数传递。那就是你的$_[0]
。您要传递的两个参数将以 $_[1]
和 $_[2]
.
您的变量 $boxA
和 $boxB
已经是引用,但您使用额外的 \
运算符传递它们。这意味着在尝试对它们调用 Tk 方法之前,您必须在回调子中取消引用它们。 - 或者在回调定义中删除 \
:
use Tk;
use strict;
use warnings;
my $mw = MainWindow -> new();
my @arr = qw(1 2 3 4 5);
my $button = $mw -> Button (-text=>"Push me", -command => \&buttonCall) -> pack;
sub callee{
my $boxARef = $_[1];
my $boxBRef = $_[2];
my $index = $boxARef -> curselection();
$boxBRef -> selectionSet($index);
}
sub buttonCall{
my $boxA = $mw -> Listbox(-exportselection=>0, -selectmode => 'browse') -> pack;
$boxA -> insert('end', @arr);
my $boxB = $mw -> Listbox(-exportselection=>0, -selectmode => 'multiple') -> pack;
$boxB -> insert('end', @arr);
$boxA -> bind ('<<ListboxSelect>>' => [\&callee,$boxA,$boxB] );
}
MainLoop;