Как понять и уничтожить использование POE-Tk? - PullRequest
2 голосов
/ 18 июля 2009

Вот тестовый код, иллюстрирующий мою проблему;


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] Рокко Капуто объясняет;

"Tk не передает информацию о событии в POE.

Как вы знаете, постбэки - это анонимные ссылки подпрограмм, которые публикуют события POE при вызове. Помимо всего прочего, они используются в качестве тонкого, гибкого интерфейса между POE и Tk.

Постбэки благословлены, и их методы DESTROY используются для уведомления POE, когда Tk завершает работу с ними. С точки зрения Tk, единственное различие между обратным вызовом и обратным вызовом - это благословение.

По какой-то причине Tk не передает параметры благословенному обратному вызову. "

Он предлагает обходной путь, но я не уверен, 1) если это проблема, которую я обнаружил, или

[1]: http://osdir.com/ml/lang.perl.poe/2004-01/msg00002.html: Tk с POE - функция bind () для нажатий клавиш "

1 Ответ

3 голосов
/ 18 июля 2009

Похоже, вы столкнулись с проблемой, которую описывает Рокко. По сути, ваше замыкание (подпункт {...}) имеет доступ к $ heap, поскольку $ heap находится в области действия при создании замыкания. С другой стороны, когда вы используете ссылку на функцию & kill_top1, оказывается, что вы не получаете никаких переданных параметров, что означает, что @_ [HEAP] не определено.

Использование замыкания, похоже, работает, но если вы хотите "подделать" его, вы можете заменить его на:

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

Я бы предпочел, чтобы интерфейс и обработка событий kill_top1 оставались такими же, как и все остальные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...