17.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 = pipename status = '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

Previous | Return to table of contents | Next