如何理解POEM-To的destroy用法?

2023-12-21

这是一些测试代码来说明我的问题;


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 之间的薄而灵活的接口等。

回发是有福的,当 Tk 处理完它们时,它们的 DESTROY 方法用于通知 POE。从 Tk 的角度来看,回调和回发之间的唯一区别就是这种祝福。

由于某种原因,Tk 不会将参数传递给受祝福的回调。”

他给出了一个解决方法,但我不确定 1) 这是否是我发现的问题或 )2 如果是,如何应用该解决方法。

[1]: http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html:Tk 使用 POE - 用于按键的 bind() 函数”


看来您确实遇到了罗科所描述的问题。基本上,您的闭包(子 {...})可以访问 $heap,因为当您创建闭包时 $heap 位于范围内。另一方面,当您使用 &kill_top1 函数引用时,您似乎没有收到任何传入的参数,这意味着 @_[HEAP] 未定义。

使用闭包似乎可行,但如果你想“伪造”它,你可以将其替换为:

kill_top1 => sub { 
    @args[KERNEL,SESSION,HEAP] = ($kernel,$session,$heap);
    kill_top1(@args);
}

这是我的偏好,只是为了保持kill_top1 的接口和事件处理与所有其他的相同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何理解POEM-To的destroy用法? 的相关文章

随机推荐