Chapter 13. Glib::MainLoop


Every GUI program has to enter a loop that will enable it to handle user actions as well as external input. To enter this loop in Gtk2-Perl we use Gtk2->main;.

In previous lessons we used the Glib::Timeout method to execute a sub on a frequency specified as an argument. This lesson will look at the more complex Glib::IO method. We will also look at the preferred Gtk2::Helper class, which servers as a Glib::IO wrapper. They will typically be used to read from files or network sockets.

13.1. Introduction - Less is More

When exposed to something new, its always good to take baby steps. We will start of with a program that is so much less it does not even feature a GUI!

This program will open a filehandle and print any new text in the file to standard out. This may sound pretty boring, but adding a GUI to this basic concept, we can create a log file reader , and if we feel really adventures, create a chat program, using sockets.

Table 13-1. Special Perl module used

Perl module name

13.1.1. The Code

The program can be found here: 'Mini Glib::IO Demo'

 1 #!/usr/bin/perl -w
 2 use strict;
 3 use Gtk2 -init;
 4 use IO::File;
 5 use Glib  qw(TRUE FALSE);
 7 my $fh = new IO::File;
 8 my $pid = $fh->open ("./test.log");
10 Glib::IO->add_watch (fileno $fh, [qw/in/],
11 		                     \&watch_callback, $fh);	
13 Gtk2->main;
15 sub watch_callback {
17 	my ($fd, $condition, $fh) = @_;
18 	my @lines = $fh->getlines;
19 	print @lines;
20 	#always return TRUE to continue the callback
21 	return TRUE;
22 }

13.1.2. The Discussion

To add a watch to a filehandle (filehandles include network sockets, files and feedback from commands), do the following:

  • Select the Perl IO module you require, in this sample, we use IO::File.

  • Initialize and open the filehandle. This is how we did it:

    my $fh = new IO::File;
    my $pid = $fh->open ("./test.log");

  • Add a watch on this filehandle to the mainloop:

    Glib::IO->add_watch (fileno $fh, [qw/in/],
    		                     \&watch_callback, $fh);


    Remember to use the fileno function on the filehandle reference.

    There is a last optional argument not used here, called $priority. This becomes VERY important as soon as you use a GUI. In order to make the GUI responsive, set this to a high number. (else your program may appear to hang)

Variations on the callback sub:

  • This sample only reads new values from the file, but should the whole file change, and you need to re-read it, use the $fh->seek ( 0, 0 ); method before using the getlines method. This will reposition the buffer pointer to the start of the file. (This method is part of IO::Seekable, which is available to IO::File). Imagine you have a file with only one line, and this line keeps changing, then you will use this method.

If you want to see the program do something, echo text into the file that was opened for reading.

# echo "Whatever U want, Whatever U need" >> ./test.log
This will be caught by the getlines method (This method is part of IO::Handle, and also available to IO::File). It should to be used in a list context, and NOT in a scalar context, thats why we have the "@lines".