2012-10-28 45 views
0

我試圖構建一個Toplevel窗口,它將顯示系統cmd的進度。我希望GUI處於活動狀態(沒有凍結和「無響應」),因此按下「取消」按鈕將終止進程,否則,完成後,激活「關閉」按鈕並禁用「取消」。在對我之前的一個問題提出建議後,我嘗試使用Proc :: Background。我發現做到這一點的唯一方法是:Perl TK與Proc ::背景正確使用(保持GUI活動?)

my $proc1; 

my $cancel = $toplevel->Button(-text => "Cancel", -command =>sub{$proc1->die;})->pack; 
my $close = $toplevel->Button(-text => "Close", -command =>sub{destroy $toplevel;}, -state=>"disabled")->pack; 

$proc1 = Proc::Background->new("x264.exe $args"); 

while ($proc1->alive == 1){ 
    $mw->update(); 
    sleep(1); 
} 

$cancel->configure(-state=>'disabled'); 
$close->configure(-state=>'normal'); 

是否有另一種更有效的方式來做到這一點(而無需等待1秒的反應)?

感謝, 馬克。

+1

您可能寫'select(undef,undef,undef,0.2);'等待0.2秒的響應。 – Basil

+0

似乎很好! – Mark

回答

1

我使用Time :: HiRes :: usleep。

use Time::HiRes qw(usleep); 
while ($proc1->alive == 1){ 
    $mw->update(); 
    usleep(100_000); //0.1 seconds 
} 

這可能是這一問題的矯枉過正,但在某些時候我們的UI應用的增長,我們迫切需要使用高分辨率定時器和異步分派,並聽取事件進行徹底的應用。爲此,我發現POE框架是一個很好的資產。

我特別使用POE與wxWidgets的,但它也兼容傳統知識: POE::Loop::Tk

1

after method(任何Tk的窗口小部件),讓您安排一個回調發生在未來某一毫秒數,和waitVariable method(您需要在頁面中搜索)將運行事件循環,直到設置了變量。

my $proc1; 
my $cancel = $toplevel->Button(-text => "Cancel", -command =>sub{$proc1->die;})->pack; 
$proc1 = Proc::Background->new("x264.exe $args"); 
my $procDone = 0; 
my $timercb = sub { 
    if ($proc1->alive) { 
     $toplevel->after(100, $timercb); 
    } else { 
     $procDone = 1; # Anything really 
    } 
}; 
$timercb(); 
$toplevel->waitVariable(\$procDone) unless ($procDone); 

(我不知道這是否代碼工作;我並不在Perl這些天代碼非常多,所以我翻譯我會在another language做...)

+0

看起來像它的作品。但遞歸地做這件事不是矯枉過正嗎? – Mark

+0

它應該只是在未來重新調度自己100ms,但我可能有點錯了! –