Napojení obsluhy signálu

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.

Zde je příklad napojení obsluhy signálu na signál:

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

V tomto (nefunkčním) kódu je toho hodně k zamyšlení. Nejdříve pojďme pojmenovat zúčastněné věci:

  • Obsluha signálu je on_button_clicked().
  • Zaháčkovali jsme ji k objektu Gtk::Button nazvanému button.
  • Když Button vyšle svůj signál clicked, zavolá se on_button_clicked().

Nyní se pojďme znovu podívat na přípojení:

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

Všimněte si, že ukazatel na on_button_clicked() nepředáváme přímo do metody connect() patřící signálu. Místo toho zavoláme sigc::ptr_fun() a do connect() předáme výsledek.

sigc::ptr_fun() generuje sigc::slot. Slot je objekt, který vypadá a působí jako funkce. Někdy se můžete setkat i s označením funkční objekt nebo functor. sigc::ptr_fun() generuje slot pro samostatnou funkci nebo statickou metodu. sigc::mem_fun() generuje slot pro členskou metodu konkrétní instance.

Zde je trochu rozsáhlejší příklad slotů v činnosti:

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

První volání connect() je stejné, jak jsme již viděli minule, nic nového.

Další už je podstatně zajímavější. sigc::mem_fun() je volaná se dvěma argumenty. První argument je some_object, což je objekt, na který náš nový slot bude ukazovat. Druhý argument je ukazatel na jednu z jeho metod. Tato konkrétní verze sigc::mem_fun() vytváří slot, který bude, když je „zavolán“, volat metodu určeného objektu, na kterou ukazuje, v tomto případě some_object.on_button_clicked().

Další věcí, která stojí v tomto příkladu za zmínku, je, že voláme connect() dvakrát pro ten samý objekt signálu. To je úplně v pořádku – když je na tlačítko kliknuto, jsou zavolány obě obsluhy signálu.

Právě jsme vám řekli, že signál clicked tlačítka očekává volání metody bez argumentu. Všechny signály mají obdobné požadavky – nemůžete zaháčkovat funkci se dvěma argumenty na signál, který neočekává žádný (ledaže použijete adaptér, jako je sigc::bind()). Proto je důležité znát, jaký typ obsluhy signálu byste měli očekávat, že se k danému signálu napojí.