0
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');
}

上面的代码片段没有成功,它只禁用了几毫秒的按钮,并且即使在批处理文件运行之前,按钮也立即处于活动状态。

4

2 回答 2

0

launch在执行system命令之前您没有关闭。

如果launch文件句柄的输出被缓冲(通常为 4KB),那么您的文件在system命令运行时可能是空的。如果system在这种情况下您的命令会立即返回,那么您的按钮也会立即重新激活。

在你的system命令之前,你应该:

close(launch);

(此外,文件句柄通常使用大写字母。)

于 2015-05-27T23:24:57.600 回答
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()orupdate()调用被激活,那么事情就会按预期进行。

示例脚本有一个缺陷:当sleep()(或任何繁忙的任务)处于活动状态时,无法对 GUI 进行更新。应用程序对用户来说似乎是冻结的。甚至窗口刷新也不再发生。如果这是一个问题,则必须以非阻塞方式重组整个脚本。在这种情况下,可以在后台启动一个新进程(正如您已经使用start命令执行的那样),但是您必须知道后台进程何时完成,然后再次启用该按钮。一种简单的方法是使用某种“信号文件”并定期检查该信号文件是否是从后台进程创建的。这是一个适用于 Unix 系统的示例(但也应该适用于 Windows,如果system()调用中使用了自定义脚本):

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;

Pod是进一步的好读物Tk::fileevent,也许你可以AnyEvent试一试。

于 2015-06-13T10:17:35.603 回答