如何理解POE-Tk使用destroy? [英] How to undersand the POE-Tk use of destroy?

查看:73
本文介绍了如何理解POE-Tk使用destroy?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<预><代码>使用 Tk;使用 POE qw( Loop::TkActiveState );使用 Tk::Toplevel;POE::Session->create(inline_states => {_start => \&ui_start,top1 => \&top1,top2 => \&top2# ,kill_top1 => \&kill_top1,kill_top1 => 子 {$heap->{tl1}->destroy;},over => sub { 退出 }});$poe_kernel->run();退出 0;子 ui_start {我的 ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];$heap->{mw} = $poe_main_window;$but1 = $heap->{mw}->Button(-text => '退出',-宽度 => 12,-command => $session->postback("over"))->pack(-padx => 7,-side => '左',-展开 => 0 );$but2 = $heap->{mw}->Button(-text => 'Top1',-宽度 => 12,-command => $session->postback("top1"))->pack(-padx => 7,-side => '左',-展开 => 0 );$but2 = $heap->{mw}->Button(-text => 'Top2',-宽度 => 12,-command => $session->postback("top2"))->pack( -padx => 7,-side => '左',-展开 => 0 );$but3 = $heap->{mw}->Button(-text => '杀死 TL',-宽度 => 12,-command => $session->postback("kill_top1"))->pack( -padx => 7,-side => '左',-展开 => 0 );}子顶级1 {我的 ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];除非(Tk::Exists($heap->{tl1})) {$heap->{tl1} = $heap->{mw}->Toplevel( title => "Top1");}}子top2{我的 ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];$heap->{tl2} = $heap->{mw}->Toplevel( title => "Top2"​​);$heap->{tl1}->destroy if Tk::Exists($heap->{tl1});}子 kill_top1 {我的 ($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错误:无法在 C:\scripts\alias\res 的未定义值上调用方法destroy"ource\alias_poe_V-3_0_par.pl 第 328 行,第 365 行.Tk::Error: Can't call method "destroy" on an undefined value at C:\scripts\alias\resource\alias_poe_V-3_0_par.pl 第 328 行,第 365 行.Tk::After::once 在 C:/Perl/site/lib/Tk/After.pm 第 89 行[once,[{},undef,100,once,[\&POE::Kernel::_poll_for_io]]](之后"脚本)

在这篇文章中[链接文本][1] Rocco Caputo 解释了;

Tk 没有将事件信息传递给 POE.

如您所知,回发是匿名子例程引用,它们在调用 POE 事件时发布.它们被用作 POE 和 Tk 之间的薄而灵活的接口.

回发是有福的,它们的 DESTROY 方法用于在 Tk 完成时通知 POE.从 Tk 的角度来看,回调和回发的唯一区别就是这种祝福.

出于某种原因,Tk 不会将参数传递给受祝福的回调."

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

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

解决方案

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

使用闭包似乎有效,但如果您想伪造"它,您可以将其替换为:

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

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

Here is some test code to illustrate my problem;


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});
}

If I uncomment the version of the inline state kill_top1, all is well. If I use the version (as shown) that calls the anonymous sub, I get;


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)

In this posting [link text][1] Rocco Caputo explains;

"Tk is not passing the event information to POE.

As you know, postbacks are anonymous subroutine references that post POE events when they're called. They're used as a thin, flexible interface between POE and Tk, among other things.

Postbacks are blessed, and their DESTROY methods are used to notify POE when Tk is done with them. From Tk's point of view, the only difference between a callback and a postback is this blessing.

For some reason, Tk does not pass parameters to a blessed callback."

He gives a workaround, but I am not sure 1) if this is the issue I have uncovered or )2 if it is, how to apply the workaround.

[1]: http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html :Tk With POE - bind() function for keypresses"

解决方案

It sure looks like you've hit the problem that Rocco is describing. Basically, your closure (the sub {...}) has access to $heap because $heap is in scope when you create the closure. On the other hand, when you use the &kill_top1 function reference it appears you're not getting any parameters passed in, which means @_[HEAP] is undefined.

Using the closure seems to work, but if you wanted to "fake" it, you could replace it with:

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

This would be my preference, just to keep the interface to, and event handling of, kill_top1 the same as all the others.

这篇关于如何理解POE-Tk使用destroy?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆