perl - 如何理解POEM-To destroy的使用?

标签 perl tk-toolkit poe

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


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/

相关文章:

perl - system() 返回的值是否与 "$?"相同?

perl - 如何使用命令行参数从 bash 运行 perl 脚本?

c - TCL GUI 在 Windows 上查看 "native"有哪些选项?

perl - 我在哪里可以阅读 POE(Perl 对象环境)的清晰解释?

perl - 在 Perl 中编写模块化聚合器和规范器

arrays - Perl:一次从多个数组中进行grep

arrays - 是否有内置函数来清除所有变量值

python - 如何在 Pygame 中使用 Tkinter 获取表单输入?

python-3.x - tkinter canvas - 从事件中提取对象 ID?