Signal slot concept

from Wikipedia, the free encyclopedia

Signals and slots are a programming concept . They implement an event-controlled program flow or event-controlled communication between program objects . The term was originally coined by the Qt library , but is now also used by a number of other program libraries . The concept can be seen as an application of the observer design pattern. It is used as an alternative to direct callback functions (Engl. Callbacks ) used when these be too inflexible or not type safe prove (z. B. complex in the development of graphical applications ).

overview

Signals are “messages” that are given ( emitted ) when an event occurs . A slot is basically a normal function that can be linked to a signal in a certain way. Slots and signals initially “know” nothing of each other. The actual program logic is only created through the link: Each time the signal is issued, the connected slot is then called. A signal can also be connected to several slots so that several functions are called when an event occurs. A slot can also be connected to several signals, whereby the same function is called when different events occur.

Signal slot mechanisms are particularly often found in program libraries for creating graphical user interfaces . Here they fulfill the task of linking objects , in particular control elements, with one another and thus filling the control elements of the surface such as buttons and list boxes with functionality.

The Qt C ++ library is probably the best known example of the use of signals and slots. They are implemented there using keywords such as signal , slot and emit , newly introduced in C ++ , which, before they are removed by the C ++ preprocessor, help Qt's own "Meta Object Compiler" ( moc ) to create additional C ++ codes.

There are also various program libraries that implement signal slot mechanisms using generic programming ( templates ) and functors , such as the Boost library or libsigc ++ , a signal slot library that is used by the gtkmm library, for example .

advantages

Signals and slots are easier and more flexible to use than callbacks if they comply with type security , but this is slightly at the expense of speed because of the overhead. However, the difference is hardly relevant in practice.

The syntax of signals and slots can often appear simpler than that required for callbacks or method pointers .

Examples with Qt

Predefined signals and slots

With Qt , many of the included classes already have various predefined signals and slots that can be used. The following example should show how you can use this to program basic functions in a GUI .

#include <QCheckBox>
#include <QObject>
#include <QMainWindow>
#include <QWidget>
#include <Qt>

class MainWindow: QMainWindow {
private:
    QWidget w;
    QCheckBox c("Fenster sichtbar", this);
    
public:
    MainWindow(QWidget *parent, Qt::WindowFlags flags): QMainWindow(parent, flags) {
        ui.setupUi(this);
        connect(&c, SIGNAL(clicked(bool)), &w, SLOT(setVisible(bool)));
    }
};

You can see the constructor of the main window. The line ui.setupUi(this);is used to generate the user interface and is not explained in more detail here (see Qt documentation). The following two lines are used to create an empty window widget wand a checkbox widget labeled with the text "Window visible" c, which appears in the main window.

Then connectthe connection of both objects is achieved by means of . The signal of clickedthe checkbox serves as the signal, which is then emitted when the user clicks on the box. The status after clicking, i.e. whether the box is checked or not, is transferred as a Boolean parameter . setVisibleis a slot that can be used to control whether all widgets are visible or not. SIGNALand SLOTare Qt's own key words to identify signals and slots as such; they are recognized by the meta-object compiler .

After starting the program, the second, empty window would appear or disappear with each click on the checkbox.

Example of self-created signals and slots

A simple class shows how signals and slots work in the Qt library. The class Zahlstores a value and has two functions to change or read this value:

// Number.h

#include <QObject>

class Number: QObject {
    Q_OBJECT
    
private:
    int value;
    
public:
    Number(): value(0) { }
    
    int getValue() const {
        return value;
    }
    
slots:
    void setValue(int value) {
        if (value != this->value) {
            this->value = value;
            emit onChange(value);
        }
    }
    
signals:
    void onChange(int newValue);
};


// main.cpp

#include <Number.h>
#include <QObject>

int main(void) {
    Number a, b; // a.getValue() == 0, b.getValue() == 0
    
    a.setValue(5); // a.getValue() == 5, b.getValue() == 0
    b.setValue(48); // a.getValue() == 5, b.getValue() == 48
    
    QObject::connect(&a, SIGNAL(onChange(int)), &b, SLOT(setValue(int)));
    
    a.setValue(12); // a.getValue() == 12, b.getValue() == 12
    b.setValue(23); // a.getValue() == 12, b.getValue() == 23
}

The class Numberis derived from the class QObjectthat contains the necessary functions for the use of signals and slots. Q_OBJECTis a macro that must be included in all classes in which signals or slots are declared. The function setValue()is declared as a slot, i. i.e., it can be connected to signals such as onChange(). The meta-object compiler Numberuses this declaration of the class to generate additional source code that contains functions for using the newly declared signals and slots. The programmer no longer has to implement any functions for the signals.

If signals are emitactivated with, all slots that were connected to this signal during the runtime of the program are called. This connection of signals and slots happens with connect()(for a better understanding, see web links: Qt documentation on signals and slots) and can also be canceled again. It connect()is also checked whether the specified signals and slots exist and whether the types of the parameters match. The connected signals and slots (each instance of a class and a function) are managed in a list. Any number of slots can be assigned to a signal.

In the example, the instances aand receive bthe value 0 during initialization. With a.setValue(5);and b.setValue(48);, the value of aand is bchanged and the signal is onChange()activated. Since setValue()no slot is connected to the signals of both instances with these first calls , activating the signal does nothing. Only after the signal has been a.onChange()connected to the slot b.setValue()with connect()is athe function b.setValue()called and the value of bchanged when the value of is changed. The last call b.setValue(23)has no effect a, because b.onChange()no slot is connected to the signal .

Implementations

Web links