Table of Contents
gtkmm widget classes have signal accessor methods, such as Gtk::Button::signal_clicked, which allow you to connect your signal handler. Thanks to the flexibility of libsigc++, the callback library used by gtkmm, the signal handler can be almost any kind of function, but you will probably want to use a class method. Among GTK+ C coders, these signal handlers are often named callbacks.
Here's an example of a signal handler being connected to a signal:
#include <gtkmm/button.h> void on_button_clicked() { std::cout << "Hello World" << std::endl; } main() { Gtk::Button button("Hello World"); button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked)); }
There's rather a lot to think about in this (non-functional) code. First let's identify the parties involved:
The signal handler is on_button_clicked()
.
We're hooking it up to the Gtk::Button
object called button
.
When the Button emits its clicked
signal, on_button_clicked()
will be
called.
Now let's look at the connection again::
... button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked)); ...
Note that we don't pass a pointer to on_button_clicked()
directly to the signal's
connect()
method. Instead, we call sigc::ptr_fun()
, and pass the result to
connect()
. What's that sigc::ptr_fun()
function for?
sigc::ptr_fun() is a factory function
which generates
sigc::pointer_functors
that are implicitly converted into sigc::slots.
A slot is an object which looks and feels like a function, but is actually an object.
These are also known as function objects
, or functors
.
sigc::pointer_functors
are functors as well and there are many other functor
types like, e.g., sigc::mem_functors
which are generated by sigc::mem_fun().
Any functor that can be called with the argument types of the slot can be implicitely converted
into a slot, i.e. you can pass any compatible functor into a function that expects a sigc::slot.
Here's a slightly larger example of slots in action:
void on_button_clicked(); class some_class { void on_button_clicked(); }; some_class some_object; main() { Gtk::Button button; button.signal_clicked().connect( sigc::ptr_fun(&on_button_clicked) ); button.signal_clicked().connect( sigc::mem_fun(some_object, &some_class::on_button_clicked) ); }
The first call to connect()
is just like the one we saw last
time; nothing new here. The next is more interesting. sigc::mem_fun()
is
called with two arguments. The first argument
is "some_object", which is the object that our new slot will be pointing at; the
second argument is a pointer to one of its methods. This particular
version of sigc::mem_fun()
creates a slot which will, when "called", call
the pointed-to method of the specified object, in this case
some_object.on_button_clicked().
Another thing to note about this example is that we placed the call to
connect()
twice for the same signal object. This is perfectly
fine - when the button is clicked,
both signal handlers will be called.
We just told you that the button's clicked
signal is expecting
to call a method with no arguments. All signals have
requirements like this; you can't hook a function with two arguments
to a signal expecting none (unless you use an
adapter, such as sigc::bind, of course). Therefore, it's important to know what type of
signal handler you'll be expected to connect to a given signal.