Conectar gestores de señales

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.

Aquí hay un ejemplo de un gestor de señales que se conecta a una señal:

#include <gtkmm/button.h>

void on_button_clicked()
{
    std::cout << "Hello World" << std::endl;
}

int main()
{
    Gtk::Button button("Hello World");
    button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
}

Hay mucho para pensar en este código no funcional. Primero, identifique a los grupos involucrados:

  • El gestor de señales es on_button_clicked().
  • Se engancha al objeto Gtk::Button llamado button.
  • Cuando el botón emita su señal clicked, se llamará a on_button_clicked().

Ahora, mire la conexión nuevamente:

    ...
    button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
    ...

Tenga en cuenta que no se le pasa un puntero a on_button_clicked() directamente al método de la señal connect(). En su lugar, se llama a sigc::ptr_fun(), y se le pasa el resultado a connect().

sigc::ptr_fun() genera un sigc::slot. Un «slot» es un objeto que se comporta como una función, pero en realidad es un objeto. Estos también se llaman objetos función, o funtores. sigc::ptr_fun() genera un «slot» para una función independiente o un método estático. sigc::mem_fun() genera un «slot» para un método miembro de una instancia particular.

Aquí hay un ejemplo ligeramente más amplio de los «slots» en acción:

void on_button_clicked();

class some_class
{
    void on_button_clicked();
};

some_class some_object;

int 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) );
}

La primera llamada a connect() es igual a la que vio la última vez; no hay nada nuevo aquí.

La siguiente es más interesante. sigc::mem_fun() se llama con dos argumentos. El primero es some_object, que es el objeto al que su nuevo «slot» apuntará. El segundo argumento es un puntero a uno de sus métodos. Esta versión particular de sigc::mem_fun() crea un «slot» que, cuando se «llame», llamará al método al que apunta del objeto especificado, en este caso, some_object.on_button_clicked().

Otra cosa notable acerca de este ejemplo es que se ha hecho la llamada a connect() dos veces para el mismo objeto de señal. Esto está perfectamente bien: cuando se pulse el botón, se llamará a ambos gestores de señales.

Como se mencionó, la señal clicked del botón está esperando llamar a un método sin argumentos. Todas las señales tienen requerimientos como este: no puede enganchar una función con dos argumentos a una señal que no espera ninguno (a menos que use un adaptador, como sigc::bind(), por supuesto). Por lo tanto, es importante saber qué tipo de gestor de señales se esperará que conecte a una señal dada.