Time Flies, Memories leak...GUIDeFATE getting a timer

It appears that I have not had single blog post for 1 whole year. Let's face it, there isn't enough time in the day to everything one might want to do. Procrastination steals more than just time though. The longer one is away from a particular activity the more difficult it is to return to that activity physically or intellectually. Some of you will recall that I developed what I claimed to be the world's simplest GUI designer, GUIDeFATE. This was the topic of a couple of presentations already but as all such projects, remains in a state of flux.

One key component of a GUI is a continuous loop that keeps monitoring human interactions and responding to this by updating the interface. What if we wanted the interface to update continuously, like a monitor, without a connection with a human input trigger? It is certainly not possible, for example to create an animation by just doing foreach(1..$x){sleep $interval; updateImage();}. This merely blocks the GUI mainloop, until the loop is completed with the display updating only after the loop completes and the control goes back to the GUI's mainloop. Instead one needs an event monitor, and more specifically a timer. The ideal scenario may have been to use something like AnyEvent or Ev, but sadly this can not be applied to all the backends; at least I do not know how one might do this. What follows is my usual trawl through the internet to source examples of timers in GUI applications with each of the various backends.

Plug-in Timer

I discovered that Tk and Gtk can work with AnyEvent/AE fairly easily. Qt and Wx have their own way to create timers. While Qt seems to be supported in the documentation for Any::Event, the general recommendation appears to be not to use Qt. Qt Slots have to be predefined and can not be made on the fly. A little jiggery pokery and we have a simple way to abstract timers through multiple back ends. BUT all is not as straightforward as one would like, as I discovered when trying test animations in various backends.

To abstract the timer in the various supported back-ends, Gtk3, Gtk2 (thanks chanio), Qt4, Wx from the UI string requires a single line added to the textual representation of the UI e.g.

my $window=<<END;
|T Animation               |
| +I--------------------+  |
| | clock.svg           |  |
| |                     |  |
| |                     |  |
| |                     |  |
| |                     |  |
| |                     |  |
| +---------------------+  |
|                          |

timer 100 ecg 1


GUIDeFATE detects the timer line, and in the case above, executes the subroutine "ecg" every 100 milliseconds. Any::Event (gtk or Tk) or Wx will happily accept a callback function reference from a string...e.g. \&{"main::$functionName"}, Qt needs a predefined callback subroutine as a slot. While this subroutine could then be used to jump to the desired subroutine, there is some inflexibility in that the number of timers that one could create are limited.

Testing timers.

I figured the best visual way to test a continuous timer would be to make a slide show updating an image window; or perhaps using a image that is updated to make an animation. The easily portable way to make an animation in Perl (without added dependencies) I figured, would be to make SVG images with only minor textual changes (something Perl is good at) required to make a graphical change. Here is GUIDeFATE being used in an application running 4 different animations made by continuously redrawing an SVG file and loading the recreated image into a frame.


When I tested the timers for such animations I found 1) that Wx, Tk and Qt applications progressively used bigger and bigger amounts of memory, with Wx particularly slowing down to a stand-still after a few hundred timer loops 2) Gtk and Gtk2 seemed to use much the same amount of memory regardless of how long it ran for. Now Tk and Wx both used Image magick to put the images into the image panel. Could this be the cause? more testing is necessary.

Things to do

GUIDeFATE 0.13 is not yet on Github or CPAN...I need to sort a few things out first.

1) One of my targets is to restructure GUIDeFATE distribution so that it does not pollute the namespace as much as it does now. I would like to move the back end modules so that they are not in the root names space e.g. GUIDeFATE::GFWx. Before that (I think) I need to wipe the old GUIDeFATE from CPAN...not sure how to to do that without creating havoc.

2) I need a few methods to delete timers, change intervals, or the callback functions...should be easy, but need to to choose methods that will be easy, and of course test them.

3) I need to test on non-Linux machines...I have no Windows PCs or Macs.

Hopefully will have this ready by the next Perl Meeting, who knows?

Leave a comment

About Saif

user-pic An Orthopaedic Surgeon, A Tissue Engineering Scientist, Lecturer, (and Hobbyist Programmer, Electronics Engineer and Roboticist)