Appendix B. Signals
Prev |  | Next

## Appendix B. Signals

## Connecting signal handlers

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::mem_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.

Prev | Up | Next
Constness | Home | Writing signal handlers