Introduction to signals

Connecting to signals

When something happens, widgets can send out a signal (e.g. a button has a "pressed" signal and a checkbox has "checked" and "unchecked" signals). You can bind a signal handler to such a signal with the connect function. The first parameter is the name of the signal, this is the trigger on which the callback should be send. This name is case-insensitive, so it does not matter if you write "pressed" or "Pressed". The second parameter is the function that you want to be called when the signal is send.

Here is an example of letting a function get called when a button has been pressed.

void signalHandler()
{
    std::cout << "Button pressed" << std::endl;
}

button->connect("pressed", signalHandler);

You could also use lambda functions of course if your function is very small. This is all the code you need to close the window when your quit button gets pressed:

quitButton->connect("pressed", [&](){ window.close(); });

The signal handler can also take two parameters: the widget that emitted the signal and the name of the signal.

void signalHandler(tgui::Widget::Ptr widget, const std::string& signalName);
editBox->connect("TextChanged", signalHandler);

Custom parameters

Custom parameters can also be provided. They have to be provided when calling the connect function and will be passed to the signal handler when the event occurs. Keep in mind that when passing a variable, a copy will be made. If the signal handler needs to have access to the original variable, use std::ref.

void signalHandler1(int i);
void signalHandler2(tgui::Gui& gui, tgui::Widget::Ptr widget, const std::string& signalName);
editBox->connect("TextChanged", signalHandler1, 5);
editBox->connect("TextChanged", signalHandler2, std::ref(gui));

When connecting class member functions, you must also keep in mind that the first parameter of such function is a hidden 'this' pointer. You must always provide the value of the 'this' pointer manually.

struct Class {
    void signalHandler1();
    void signalHandler2(tgui::Widget::Ptr widget, const std::string& signalName);
    void signalHandler3(tgui::Gui& gui, tgui::Widget::Ptr widget, const std::string& signalName);
};

Class instance;

editBox->connect("TextChanged", &Class::signalHandler1, &instance);
editBox->connect("TextChanged", &Class::signalHandler2, &instance);
editBox->connect("TextChanged", &Class::signalHandler3, &instance, std::ref(gui));

Optional parameters

The widget can optionally provide information about the event that occurred. Since the connect function as shown above does not know at compile time what the signal type is, it cannot use these optional parameters. You must instead connect to the signal directly. The "pressed" signal from buttons e.g. provides the text of the button as optional parameter, so that the signal handler can distinguish which button was pressed.

void buttonClickedCallback1();
button->onPress->connect(buttonClickedCallback1);

void buttonClickedCallback2(const sf::String& buttonText);
button->onPress->connect(buttonClickedCallback2);

void buttonClickedCallback3(tgui::Widget::Ptr widget, const std::string& signalName, const sf::String& buttonText);
button->onPress->connect(buttonClickedCallback3);

Disconnecting signals

The connect function returns a unique id, which can be used to diconnect the signal handler.

unsigned int id1 = button1->connect("pressed", signalHandler);
button1->disconnect("pressed", id1);

unsigned int id2 = button2->onPress->connect(signalHandler);
button2->onPress->disconnect(id2);

It is also possible to disconnect all signal handlers that connected to a specific signal at once.

button1->disconnectAll("pressed");

button2->onPress->disconnectAll();