0

我正在尝试构建一个显示系统 cmd 进度的顶级窗口。我希望 GUI 处于活动状态(没有冻结和“无响应”),因此按下“取消”按钮将终止进程,否则,完成后,激活“关闭”按钮并禁用“取消”。根据对我之前的一个问题的建议,我尝试使用 Proc::Background。我发现这样做的唯一方法是:

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 秒响应)?

谢谢,马克。

4

2 回答 2

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 一起使用,但它也与 Tk 兼容: POE::Loop::Tk

于 2012-10-28T16:37:42.410 回答
1

after方法(任何 Tk 小部件的)允许您安排回调在未来某个毫秒数发生,并且该waitVariable方法(您需要在页面中搜索)将运行事件循环,直到设置了变量。

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

(I'm not sure if this code will work; I don't code very much in Perl these days, so I'm translating what I'd do in another language…)

于 2012-10-28T19:08:09.483 回答