我正在尝试构建一个显示系统cmd进度的Toplevel窗口。我希望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秒的响应)?
谢谢, 标记
答案 0 :(得分: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
答案 1 :(得分: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中所做的事情......)