It should be clear by now that if you want to react to an action, you must connect its signal to a signal handler that you have written, so that PHP-GTK 2 can call that function whenever the signal is triggered. Let's look into how you can connect signals to signal handlers.
There are 4 main functions that you can use to connect signals to callbacks:
First we'll look into how to connect a signal to a signal handler in the most simplest way. We'll be using, you guessed it, the connect_simple method.
Of course, it is vital that you know the names of the signals that you would want to connect to. The PHP-GTK 2 documentation contains a list of all signals that are relevant for a particular widget. Once you know that, and once you have written a function that contains the code you want to be executed when the signal is generated all you have to do is:
${widget}->connect_simple('{signal-name}', '{callback-name}'); |
To make things a little clearer, let's take a full fledged example. Here, we add a button to a window. When a user clicks the button, the application quits:
Example 9.1. A simple connection
<?php $win = new GtkWindow(); $but = new GtkButton('Click to Quit!'); $win->add($but); $win->show_all(); $but->connect_simple('clicked', 'quit'); function quit() { echo "You have quit!\n"; Gtk::main_quit(); } Gtk::main(); ?> |
It's quite a simple program. We create a button and a window, add the button to the window and show them. The line we are concerned with is:
$but->connect_simple('clicked', 'quit'); |
You can see in the quit function definition that we display a message and then call the Gtk::main_quit() function to exit the program.
What if I connect the same signal twice to two different callbacks?, I hear you ask. Well, the signal handlers will simply be called in the order in which they were connected.
An example to make things crystal clear:
Example 9.2. Multiple signal connections
<?php $win = new GtkWindow(); $but = new GtkButton('Click to Quit!'); $win->add($but); $win->show_all(); $but->connect_simple('clicked', 'first'); $but->connect_simple('clicked', 'second'); $but->connect_simple('clicked', 'third'); function first() { echo "I am the first function!\n"; } function second() { echo "I am the second function!\n"; } function third() { echo "And I'm the function that's going to stop this program!\n"; Gtk::main_quit(); } Gtk::main(); ?> |
OK, but what if I connect the signal to the same callback a hundred times? The callback will be invoked a hundred times. But there's no reason anyone would want to do this.
Can I connect multiple signals to the same callback? Yes, and in fact this is actually very useful. Many applications will have multiple ways of quitting the program: the regular "cross" button, a "quit" button on the file menu etc. You can connect signals for each one of them to a single quit function. You don't have to worry about where the signal came from, you just know that the user wants to quit the application.
Sometimes, its useful to know which widget had triggered a particular signal. If your application has more than one button, and you've connected all their clicked signals to a single callback, you'd definitely want to know which button the signal came from. It is in fact efficient to write a single signal handler for multiple signals.
Here is where the connect method comes into the picture. This method passes the object of the widget that generated the signal as the first parameter to the signal handler.
$button1 = new GtkButton('First'); $button2 = new GtkButton('Second'); $button1->connect('clicked', 'show'); $button2->connect('clicked', 'show'); function show($whichbutton) { echo $whichbutton->get_label(); } |
It is also useful at times if you could pass custom parameters to your signal handlers. PHP-GTK 2 provides this functionality in both the connect and connect_after methods. You simply pass your parameters after the second argument to both these methods separated by commas like this:
Example 9.3. Passing custom parameters
<?php $win = new GtkWindow(); $but = new GtkButton('Move over me!'); $win->add($but); $win->show_all(); $win->connect_simple('destroy', array('gtk', 'main_quit')); $but->connect_simple('enter-notify-event', 'showMessage', true, 'You moved the mouse'); $but->connect_simple('leave-notify-event', 'showMessage', false, 'You moved the mouse'); function showMessage($enter, $message) { if ($enter) { echo $message." over the button!\n"; } else { echo $message." away from the button!\n"; } } Gtk::main(); ?> |
Let us analyze the line that you might have seen frequently:
$window->connect_simple('destroy', array('gtk', 'main_quit')); |
Remember that whenever you connect to callback functions in an object-oriented context, the second argument to the connect_* functions must be an array. The first element of the array should point to the class that contains the callback and the second element must contain the name of the callback itself.
When the callback is static in nature (like Gtk::main_quit()), we generally specify the name of the class as a string. However if the callback is not static in nature, but is a member of your current class instead, the first element should be the special $this variable. Have a look at the tutorial on Object Oriented Programming for examples of usage in such a context. The point is to somehow make the first element of the array point to the class that contains the callback and the second element point to the callback.