这是一些测试代码来说明我的问题;
use Tk;
use POE qw( Loop::TkActiveState );
use Tk::Toplevel;
POE::Session->create(
inline_states => {
_start => \&ui_start
,top1 => \&top1
,top2 => \&top2
# ,kill_top1 => \&kill_top1
,kill_top1 => sub {
$heap->{tl1}->destroy;
}
,over => sub { exit }
}
);
$poe_kernel->run();
exit 0;
sub ui_start {
my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
$heap->{mw} = $poe_main_window;
$but1 = $heap->{mw}->Button(
-text => 'Exit',
-width => 12,
-command => $session->postback("over")
)->pack( -padx => 7,
-side => 'left',
-expand => 0 );
$but2 = $heap->{mw}->Button(
-text => 'Top1',
-width => 12,
-command => $session->postback("top1")
)->pack( -padx => 7,
-side => 'left',
-expand => 0 );
$but2 = $heap->{mw}->Button(
-text => 'Top2',
-width => 12,
-command => $session->postback("top2")
)->pack( -padx => 7,
-side => 'left',
-expand => 0 );
$but3 = $heap->{mw}->Button(
-text => 'Kill TL',
-width => 12,
-command => $session->postback("kill_top1")
)->pack( -padx => 7,
-side => 'left',
-expand => 0 );
}
sub top1 {
my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
unless(Tk::Exists($heap->{tl1})) {
$heap->{tl1} = $heap->{mw}->Toplevel( title => "Top1");
}
}
sub top2 {
my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
$heap->{tl2} = $heap->{mw}->Toplevel( title => "Top2");
$heap->{tl1}->destroy if Tk::Exists($heap->{tl1});
}
sub kill_top1 {
my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
$heap->{tl1}->destroy if Tk::Exists($heap->{tl1});
}
如果我取消注释内联状态kill_top1的版本,一切都很好。如果我使用调用匿名子的版本(如图所示),我会得到;
C:\scripts\alias\resource>alias_poe_V-3_0_par.pl
error:Can't call method "destroy" on an undefined value at C:\scripts\alias\res
ource\alias_poe_V-3_0_par.pl line 328, line 365.
Tk::Error: Can't call method "destroy" on an undefined value at C:\scripts\alias
\resource\alias_poe_V-3_0_par.pl line 328, line 365.
Tk::After::once at C:/Perl/site/lib/Tk/After.pm line 89
[once,[{},undef,100,once,[\&POE::Kernel::_poll_for_io]]]
("after" script)
在这篇文章中[链接文本][1] Rocco Caputo 解释道;
“Tk 没有将事件信息传递给 POE。
如您所知,回发是匿名子例程引用,在调用 POE 事件时发布 POE 事件。它们被用作 POE 和 Tk 之间的薄而灵活的接口(interface)等。
回发是有福的,当 Tk 处理完它们时,它们的 DESTROY 方法用于通知 POE。从 Tk 的角度来看,回调和回发之间的唯一区别就是这种祝福。
出于某种原因,Tk 不会将参数传递给受祝福的回调。”
他给出了一种解决方法,但我不确定 1) 这是否是我发现的问题,或 )2 如果是,如何应用该解决方法。
[1]:http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html :Tk 使用 POE - 用于按键的 bind() 函数”
最佳答案
看来您确实遇到了 Rocco 所描述的问题。基本上,您的闭包(子 {...})可以访问 $heap,因为当您创建闭包时 $heap 位于范围内。另一方面,当您使用 &kill_top1 函数引用时,您似乎没有收到任何传入的参数,这意味着 @_[HEAP] 未定义。
使用闭包似乎可行,但如果你想“伪造”它,你可以将其替换为:
kill_top1 => sub {
@args[KERNEL,SESSION,HEAP] = ($kernel,$session,$heap);
kill_top1(@args);
}
这是我的偏好,只是为了保持kill_top1 的接口(interface)和事件处理与所有其他的相同。
关于perl - 如何理解POEM-To destroy的使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1145532/