Perl/TkFAQ-18.1.如何让Perl/Tk响应来自X以外的事件?

王朝perl·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

原文:

18.1. How does one get Perl/Tk to act on events that are not coming from X?

On 22 Nov 1995 (Yaniv Bargury) bargury@milcse.cig.mot.com wrote:

I need to write a GUI monitor, that displays the status and controls a set of processes running in the background. The idea is to have the GUI application start a few child processes, command the children through pipes from the GUI to the children, and display the children status coming on pipes from the children to the GUI in real time.

The GUI must not be busy waiting, because the CPU resources are limited. This excludes using the Tk_DoWhenIdle as explained in the manual.

The usual way to do this is to for the GUI process to have one select() in its main loop. That select() should wait for X events or input from the pipes leading from the children.

How do you do this?

To which Nick Ing-Simmons <nik@tiuk.ti.com> replied:

fileevent - it is the hook into the select() in the mainloop.

In addition Avi Deitcher <avi@morgan.com> replied with:

I wrote something similar to effectively do a tail -f on multiple hosts, displaying the result on separate text widgets. Do the following:

parent child child child ..

with a one-way pipe from each child to the parent. Set up the following:

$main->fileevent(FILEHANDLE,status,subroutine);

for each pipe that you have. This will cause pTk to monitor the FILEHANDLE and call 'subroutine' when an event happens on that handle. In this case: FILEHANDLE = pipenamestatus = 'readable' or 'writable' or 'exception' and subroutine = any subroutine that you want.

To provide a concrete example of fileevent usage Stephen O. Lidie wrote a wonderful little GUI tail monitor he calls tktail: #!/usr/local/bin/perl -w # # tktail pathname use English; use Tk; open(H, "tail -f -n 25 $ARGV[0]|") or die "Nope: $OS_ERROR"; $mw = MainWindow->new; $t = $mw->Text(-width => 80, -height => 25, -wrap => 'none'); $t->pack(-expand => 1); $mw->fileevent(H, 'readable', [\&fill_text_widget, $t]); MainLoop; sub fill_text_widget { my($widget) = @ARG; $ARG = <H>; $widget->insert('end', $ARG); $widget->yview('end'); } # end fill_text_widget

An example of how one might use such a script would be to create and monitor a file foo like so: echo Hello from foo! > foo tktail foo & echo "A ship then new they built for him/of mithril and of elven glass" --Bilbo \ >> foo

译文:

18.1. 如何让Perl/Tk响应来自X以外的事件?

1995年11月22日,Yaniv Bargury写道:

我想写一个图形用户界面的监控器,用来显示状态并控制一系列后台运行的进程。我的想法是让GUI程序启动一些子进程,并通过管道向这些子进程传递命令,然后实时的显示由子进程传递回来的状态信息。

我要求GUI程序不能因为CPU忙而出现等待状态。这就无法使用手册中提到的Tk_DoWhenIdle。

实现这个目的,常规的方法是在GUI程序的mainloop中使用一个select()。这个select()应该等待X事件或者来自子进程的管道的输入。

你如何实现这个呢?

对此,Tk的作者Nick Ing-Simmons回答到:

fileevent – 它是mainloop中实现select()的一种方法。

另外,Avi Deitcher还回答到:

我写了一个程序,实现类似于高效的对多个对象实现tail -f的功能,同时在各个文本组件中显示结果。实现如下:

父进程

子进程

子进程

……

从每个子进程到父进程使用一个单路管道。对每个管道设置如下:

$main -> fileevent(FILEHANDLE,status,subroutine);

这样就可以让pTk监控每一个文件句柄,并且当某个句柄中发生一个事件时调用子程序’subroutine’来处理。在这个例子中:文件句柄 FILEHANDLE可以是管道名称,状态status可以是‘readable’或者‘writable’或者‘exception’,而子程序 subroutine则可以是你希望的任何子程序。

为了提供一个关于fileevent用法的具体例子,Stephen O. Lidie写了一个非常出色的GUI监控器的小程序,他称之为tktail:

#!/usr/local/bin/perl -w

#

# tktail pathname

use English;

use Tk;

open(H, "tail -f -n 25 $ARGV[0]|") or die "Nope: $OS_ERROR";

$mw = MainWindow->new;

$t = $mw->Text(-width => 80, -height => 25, -wrap => 'none');

$t->pack(-expand => 1);

$mw->fileevent(H, 'readable', [\&fill_text_widget, $t]);

MainLoop;

sub fill_text_widget {

my($widget) = @ARG;

$ARG = <H>;

$widget->insert('end', $ARG);

$widget->yview('end');

} # end fill_text_widget

下面是关于如何使用创建一个文件foo,然后用上面的脚本来进行监控的例子:

echo Hello from foo! > foo

tktail foo &

echo "A ship then new they built for him/of mithril and of elven glass" --Bilbo >> foo

(译者注:因为上面的例子中使用了Unix系统中的tail命令,所以在Windows系统下无法运行……但是在Unix/Linux系统中确实是可以正常使用的。)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航