0

下面是一个带有 TK 的 Perl 代码示例:

my $btn_start = $mw->Button(-image => $img_start, -command => \&start)->pack;
MainLoop;


sub start{
my $topWin = $mw -> Toplevel;
my $entry = $topWin->Label(-textvariable=>\my $process)->pack();
$process="start 1st";
system("long_command.exe");
$process.="\nstart 2nd";
system("another_command.exe");
.
.
.
$process.="\nstart nth";
system("ncommand.exe");
}

问题是当我按下按钮时,只有在 system() 命令完成运行后才会打开顶层窗口(为什么它们会先于其他任何东西启动??),而且 $btn_start 在整个过程中仍然是“活动的”。我试图在每个 system() 命令之后实现状态更新。

你能给些建议么?

提前谢谢你,马克。

4

4 回答 4

4

在运行 system() 命令之前,添加一个

$mw->update()

陈述。发生的情况是主循环不时更新窗口;在您的情况下,在下一次计划更新发生之前(仅当 start() 返回主循环时才会发生), system() 被调用并且在它返回之前,不会执行任何其他操作 - 因为一切都在同一个进程中运行.

但是,如果你想正确地做这些事情,你应该分叉你的过程。否则,您的应用程序在命令执行期间将不会反应。

于 2012-10-15T16:29:55.600 回答
1

在您的情况下,用户界面(按钮、标签等)和它们运行的​​任务(system)都由同一个进程和同一个线程运行。这是编写 GUI 程序的幼稚方法。

为了获得您正在寻找的效果——一个活动的用户界面,而其他事情在后台发生——你需要研究如何同时运行它们。

于 2012-10-15T16:30:29.280 回答
1

[注意:我无权访问正在运行的 Tk,因此以下是基于第一原则和文档的推测。你被警告了。]

Tk 没有重新获得控制权以更新 UI。正在发生的事情是您已经创建了新的TopLevel,但没有将控制权交还给以MainLoop允许绘制它。最终,start返回,将控制权交还给MainLoop,它一次执行所有挂起的更新。

如果您希望在您处于潜艇中间时更新 UI,您必须定期调用update最外面的有趣Widget以便将控制权交还给MainLoop一个咒语。在你的情况下,这看起来是

$mw->update();

另请参阅updateperldoc Tk::Widget

于 2012-10-15T16:53:11.357 回答
0

问题是在等待子进程完成时system停止一切(在同一个线程中)。这包括停止 GUI 事件队列的服务,该队列用于驱动各种事情(包括重绘)。考虑使用Proc::Background模块异步运行子进程(使用常规计时器来确定一个任务是否已完成以及下一个任务是否应该开始,假设一次只执行一项对您的代码很重要)。

于 2012-10-16T10:34:13.433 回答