2009-07-17 4 views
2

Hier ist ein Testcode, um mein Problem zu veranschaulichen;Wie unterschreiben Sie die POE-Tk Verwendung von zerstören?


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

Wenn ich die Version des Inline-Zustand kill_top1 Kommentar-, ist alles gut. Wenn ich die Version (wie gezeigt) verwende, die den anonymen Sub aufruft, bekomme ich;


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 diesem Beitrag [Linktext] [1] Rocco Caputo erklärt;

„Tk ist die Ereignisinformationen zu POE nicht vorbei.

Wie Sie wissen, Postbacks anonyme Unterprogramm Referenzen sind die POE Ereignisse veröffentlichen, wenn sie genannt werden. Sie sind als dünne, flexible Schnittstelle zwischen POE verwendet und Tk, unter anderem.

Postbacks sind gesegnet, und ihre DESTROY-Methoden werden verwendet, um POE zu benachrichtigen, wenn Tk mit ihnen erledigt ist.Aus Sicht von Tk ist der einzige Unterschied zwischen einem Callback und einem Postback dieser Segen.

Aus irgendeinem Grund übergibt Tk keine Parameter an einen gesegneten Rückruf. "

Er gibt einen Workaround, aber ich bin mir nicht sicher 1) wenn dies das Problem ist, das ich aufgedeckt habe oder 2) wenn es ist, wie man die Problemumgehung anwendet.

[1]: http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html. Tk mit POE - bind() Funktion für Tastenanschläge“

+1

Wenn Sie den ersten $ Heap -> {tl1} -> zerstören, wo bekommen Sie Ihre $ Heap aus? Ich kann es nirgends definiert sehen. – Inshallah

+0

Was ist los mit dem Komma wo sie hingehören? Sie verletzen meine Augen. –

+0

Natürlich ist nichts falsch daran Kommas am Ende der Zeile zu setzen. Ich fing an, sie am Anfang zu setzen, nachdem ich einen Syntaxfehler erstellt hatte, als ich eine Gruppe von Einstellungen an einem Widget ausschneiden und einfügen ließ und eine Zeile ohne Komma in der Mitte des Stapels verließ. Ich entschuldige mich, wenn Sie dadurch irgendwelche Beschwerden haben. - jpolache 0 Sek. Her [Diesen Kommentar löschen] – jpolache

Antwort

3

Es sieht aus wie sicher das Problem getroffen haben, die Rocco beschreibt Grundsätzlich Ihre Schließung (der sub {.. .}) hat Zugriff auf $ heap, da $ heap beim Erstellen der Closure im Bereich ist. Wenn Sie jedoch die Funktionsreferenz & kill_top1 verwenden, scheint es, dass Sie keine übergebenen Parameter erhalten, was @_ bedeutet. HEAP] undefiniert

mit der Schließung scheint zu funktionieren, aber wenn man wollte „fake“ es, können Sie es mit ersetzen könnte.

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

Dies wäre meine Präferenz, nur um die Schnittstelle zu und die Ereignisbehandlung von kill_top1 genauso zu halten wie alle anderen.

Verwandte Themen