sub push_button2
{
$but2->configure(-state => 'disabled');
open(launch, "+>C:\\integration\\check_label\\launch_check_label.bat") or die "Couldn't open file launch_check_label.bat$!";
print launch "$ARGV[1]:\n";
print launch "perl C:\\integration\\check_label\\check_label.pl $ARGV[0] $ARGV[1] $text";
system("start C:\\integration\\check_label\\external_command.bat");
$but2->configure(-state => 'normal');
}
上面的代码片段没有用完,它只禁用了几毫秒的按钮,并且即使在批处理文件运行之前,按钮仍然处于活动状态。
答案 0 :(得分:0)
在执行launch
命令之前,您没有关闭system
。
如果缓存了launch
文件句柄的输出(通常为4KB),那么在运行system
命令时,您的文件可能是空的。如果您的system
命令在这种情况下立即返回,那么您的按钮也会立即重新激活。
在你的system
命令之前,你应该:
close(launch);
(另外,传统上使用全大写的文件句柄。)
答案 1 :(得分:0)
您的方法存在一些问题。首先,顺序"禁用按钮","做一些非Tk-ish","启用按钮"不起作用,按钮始终保持启用状态。原因是显示更改仅在回调返回或显式update()
或idletasks()
被调用时执行。为了证明这一点,在以下示例中,永远不会禁用该按钮:
use Tk;
my $mw = tkinit;
my $b; $b = $mw->Button(-text => 'Click me!', -command => sub {
$b->configure(-state => 'disabled');
# $mw->idletasks; # or alternatively: $mw->update;
sleep 10; # simulate some task
$b->configure(-state => 'normal');
})->pack;
MainLoop;
但是,如果idletasks()
或update()
来电被激活,那么事情会按预期进行。
示例脚本有一个缺陷:当sleep()
(或任何繁忙的任务)处于活动状态时,不能对GUI进行任何更新。该应用程序似乎被冻结给用户。即使是窗户刷新也不会再发生了。如果这是一个问题,则必须以非阻塞方式重构整个脚本。在这种情况下,可以在后台启动一个新进程(正如您已经使用start
命令执行的那样),但是您必须知道后台进程何时完成,然后再次启用该按钮。一种简单的方法是使用某种"信号文件"并定期检查此信号文件是否是从后台进程创建的。这是一个适用于Unix系统的示例(但如果在system()
调用中使用自定义脚本,也可以在Windows上运行):
use Tk;
my $mw = tkinit;
my $b; $b = $mw->Button(-text => 'Click me!', -command => sub {
$b->configure(-state => 'disabled');
# no idletasks/update necessary now
system("(rm -f /tmp/signal_file; sleep 10; touch /tmp/signal_file) &");
my $repeater; $repeater = $mw->repeat(1000, sub {
if (-e "/tmp/signal_file") {
unlink "/tmp/signal_file";
$b->configure(-state => 'normal');
$repeater->cancel;
}
});
})->pack;
MainLoop;
这种方法不是很优雅,因为它需要定期检查。可以使用Tk::IO
模块编写更优雅的方法,但这可能仅适用于Unix平台:
use Tk;
use Tk::IO;
my $exec_fh;
my $mw = tkinit;
my $b; $b = $mw->Button(-text => 'Click me!', -command => sub {
$b->configure(-state => 'disabled');
# no idletasks/update necessary now
$exec_fh = Tk::IO->new(-linecommand => sub {
# empty, we're not interested in the output
}, -childcommand => sub {
$b->configure(-state => 'normal');
});
$exec_fh->exec("sleep 10");
})->pack;
MainLoop;
Tk::fileevent
Pod还有更好的读数,也许你可以试试AnyEvent
。