即使使用了不同的变量ref,为什么waitVariable调用不是独立的?

Tru*_*ueY 5 linux perl tk-toolkit

我是Tk的新手,我想知道这个问题是否是正常的Tk行为.

简而言之:我有一个Perl/Tk(Tk版本804.028)脚本,该脚本使用两个Tk :: ExecuteCommand(v1.6)小部件.这些对象有一个execute_command方法,该方法使用定义的fileevent回调来读取已执行命令的stdout,并在完成后返回.它通过waitVariable的使用来解决.但似乎两个ExecuteCommand一起启动它们只在较慢返回时才返回.完成之后我可能会立即得到更快的回报.

我做了一个小测试Perl/Tk脚本来演示这个问题:

#!/usr/bin/perl

use strict;
use warnings;
use Tk;
use Tk::ROText;

my $MAIN = new MainWindow -title => "TEST";
my $text = $MAIN->Scrolled('ROText')->pack(qw/-expand 1 -fill both/);

sub pr { # Write into ROText widget
  $text->insert('end', join '', @_); $text->yview('end');
}
pr "Tk version ", Tk->VERSION, "\n";

my @v = (100, 200);
sub doo { # Button callback
  my ($rv, $txt) = @_;
  pr "B4 wait: $txt, ref=$rv, val=", $$rv, "\n";
  $MAIN->waitVariable($rv);
  pr "Aft wait: $txt, ref=$rv, val=", $$rv, "\n";
}

$MAIN->Button(-text => 'Do 0', -command => [\&doo, \$v[0], "Do 0" ]
    )->pack(qw/-expand 1 -side left -fill both/);
$MAIN->Button(-text => 'Stop 0', -command => [sub {++$v[0]; pr "Stop 0\n";} ]
    )->pack(qw/-expand 1 -side left -fill both/);
$MAIN->Button(-text => 'Do 1', -command => [\&doo, \$v[1], "Do 1" ]
    )->pack(qw/-expand 1 -side left -fill both/);
$MAIN->Button(-text => 'Stop 1', -command => [sub {++$v[1]; pr "Stop 1\n";} ]
    )->pack(qw/-expand 1 -side left -fill both/);

MainLoop();
Run Code Online (Sandbox Code Playgroud)

这将绘制一个ROText小部件和4个按钮([Do 0] [Stop 0] [Do 1] [Stop 1])(参见附图).单击"执行"按钮,将调用该函数doo,该函数将一直等到指定的标量发生更改.按下"停止"按钮时,变量会发生变化.

如果在[Do 0] [Stop 0] [Do 1] [Stop 1]命令中按下按钮,则输出似乎正常(参见第2-7行).但是如果"任务"并行启动,则只有两个回调都停止时,两个回调才会完成.因此按下[Do 0] [Do 1] [Stop 0] [Stop 1](见第8-13行)中的按钮会产生奇怪的结果(见图).

在此输入图像描述

我对第二次测试的期望是第一个回调函数在按下第一个停止按钮后立即返回.所以我认为输出应该是:

B4 wait: Do 0, ref=SCALAR(0x9970560), val=101
B4 wait: Do 1, ref=SCALAR(0x9970bfc), val=201
Stop 0
Aft wait: Do 0, ref=SCALAR(0x9970560), val=102
Stop 1
Aft wait: Do 1, ref=SCALAR(0x9970bfc), val=202
Run Code Online (Sandbox Code Playgroud)

它在Linux机器上运行.

我错过了什么吗?提前致谢!

UPDATE

为了绕过这个waitVariable问题,我重写了这个小部件来代替使用回调(感谢Tantalus!).现在execute_command立即返回.有两个回调,一个用于取消,一个用于完成.现在通过这些回调通知呼叫者.无论如何,我在某处读到(我现在找不到源代码)在Tk中长时间等待回调并不是一个好主意.新解决方案符合此要求.

谢谢您帮忙!

ike*_*ami 3

$widget->waitVariable(\$name)

$widget->waitVisibility

$widget->waitWindow

tk wait 方法等待几件事情之一发生,然后返回而不采取任何其他操作。返回值始终是空字符串。waitVariable 需要对 perl 变量的引用,并且该命令等待该变量被修改。这种形式通常用于等待用户完成与对话框的交互,该对话框将变量设置为交互的一部分(可能是最终的)。waitVisibility 等待 $widget 的可见性状态发生更改(如 VisibilityNotify 事件的到达所示)。此表单通常用于等待新创建的窗口出现在屏幕上,然后再执行某些操作。waitWindow 等待 $widget 被销毁。此表单通常用于等待用户完成与对话框的交互,然后再使用该交互的结果。请注意,每次需要对话框时创建和销毁窗口会使代码模块化,但会增加开销,这可以通过撤回窗口并使用 waitVisibility 来避免。

当 tk wait 方法等待时,它们以正常方式处理事件,因此应用程序将继续响应用户交互。如果事件处理程序再次调用 tkwait,则对 tkwait 的嵌套调用必须在外部调用完成之前完成。

强调我的。