2009-07-17 17 views
2

下面是一些測試代碼來說明我的問題;如何降低POE-Tk的使用破壞?


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之間的薄,靈活的接口和Tk等

回傳是有福的,它們的DESTROY方法用於在Tk完成時通知POE從Tk的角度來看,回調和回發之間的唯一區別就是這種祝福。

由於某些原因,Tk不會將參數傳遞給有福的回調函數。「

他給出了一個解決方法,但我不確定1)如果這是我發現的問題或)2如果是,如何應用該解決方法。

[1]:http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html:Tk的帶PoE - 爲按鍵bind()函數」

+1

當你做第一個$堆 - > {tl1} - >銷燬,你從哪裏得到你的$堆?我無法在任何地方看到它。 – Inshallah 2009-07-17 21:50:42

回答

3

它肯定看起來像你打的是羅科描述基本上這個問題,你的封(次{.. 。})有權訪問$ heap,因爲創建閉包時$ heap在範圍內。另一方面,當使用& kill_top1函數引用時,它看起來並沒有傳入任何參數,這意味着@_ [ HEAP]未定義

使用封閉似乎可行,但如果您想「僞造」它,您可以將其替換爲:

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

這將是我的首選,只是爲了讓kill_top1的接口和事件處理與所有其他接口保持一致。