Glade, PyGTK, gnome-python Textorial

Signals and Events

The program that we created on the previous page might look great, but it really doesn't do anything. Not only this, but you have probably noticed by now that closing the program through the window manager (clicking the 'X') does not cause the program to quit! This problem, and pretty much every other problem we might have with our program can be solved with signals and signal handlers.

Signal Handlers

As mentioned briefly before, GTK applications work on a system of signals and events. Although sometimes the terms are used interchangeably, they are not the same thing (they are interrelated though). Whenever the user interacts with the application; types a character, clicks a button, opens a menu: a event occurs. When an event occurs, the widget that the user is interacting with will emit the propper signal; "activated", "clicked", etc. The application then intercepts that signal, and passes the control off to a signal handler. A signal handler is just another name for a function (method, procedure, etc), only in the context of signal handling, it means that the function is designed to run when that signal is intercepted by your application. If you want to read more about GTK signals and events (in a python context), check out John Finlay's section on signals and callbacks in his excellent pygtk2 tutorial.

In order for signals and events to be useful, you need to know which events cause which signals, and what are some after-effects your signal handler might do by, say, returning a value or changing an object. Every object in GTK has a set of events that it can emit signals on; and for the greatest understanding of how the hierarchy works in python, you should check out the PyGTK API documentation, which outlines the whole system rather nicely. Of course, all of the information is far more useful once we know how to use the signals that these objects emit, so lets do that now.

signal_connect

Now that we know that in order to have our program do something useful when the signals are emitted, we need some way to connect signal handlers to the signals. Luckily, when libglade parses the XML .glade file, it creates all of our signals for us and places them in our widgetTree. Because the signals already exist, we can simply connect them by using the widgetTree method signal_connect(signal_name, signal_handler).

Suppose we have a signal named foo_delete, and a method named foo_delete_handler. To connect foo_delete to foo_delete_handler, we simply call signal_connect("foo_delete", foo_delete_handler). But, whenever a widget is clicked, a window closed; we emit a signal. Even in a small application, this usually means at least a dozen signals, but in any project of negligible difficulty, it means that we'd need scores of calls to signal_connect; not only that, but we'd have to fill out everything manually.

dictionaries

To combat this problem, we can use the builtin python datatype "dictionaries". A dictionary (for our purposes) is basically an associative array or a hash table; it hashes a string to a certain piece of data. The declaration of a dictionary looks something like this: my_dict = {"key1" : data, "key2" : data2 } Dictionaries make it easy for us to organize our data, port it around, and access it.

signal_autoconnect

To use dictionaries to connect our signals, we create a dictionary where the data are all signal handling functions, and the keys are all the names assigned to the signal handler in glade, and then pass it to the signal_autoconnect method of the widgetTree object. Looking back to our "foo" example, to create a dictionary and then connect the signal automatically, we would do:

my_sigs = {"foo_delete" : foo_delete_handler}
signal_autoconnect(my_sigs)

For an example as simple as this, its not really apparent how much space (or time) this could save, but consider that the dictionary can contain arbitrary many keys (and associated pieces of data, in this case a function), and that you could write a function to generate a dictionary dynamically, and you will see how this can save time and complexity in your program. If you still want manual control over signals and signal handlers, you can use the signal_autoconnect function to group your signals and handlers together neatly so that signals associated with widgets or collections of widgets stay together.

back to the Glade Environment | forward to Glade and Events
up to the index