Every interactive application needs a way for objects to communicate — a button needs to tell something that it was clicked, a sensor needs to report that a value changed, a timer needs to notify its owner that it fired. Qt's answer to this problem is the Signals and Slots mechanism: a clean, type-safe, loosely coupled approach to event-driven communication that is central to everything Qt does.
The Observer Pattern
Signals and Slots is Qt's implementation of the Observer Pattern — a software design pattern where:
- An object (the subject/sender) maintains a list of observers
- When the subject's state changes, it notifies all registered observers automatically
- Observers do not need to be known to the subject at the time the subject is written
In Qt's implementation:
- Signals are the notification mechanism (what the subject emits)
- Slots are the observer functions (what the observer executes in response)
- connect() is how subjects and observers are linked
Core Concepts
Signal
A signal is a notification emitted by an object when something happens. Signals are declared in the class using the signals: keyword (processed by MOC — see the MOC article for details).
class Sensor : public QObject {
Q_OBJECT
signals:
void temperatureChanged(double newTemperature); // Signal declaration
void thresholdExceeded(); // Signal with no data
};
Key properties of signals:
- Signals are declared, not implemented — MOC generates the implementation
- A signal can carry parameters that provide data to connected slots
- Emitting a signal is done with the
emitkeyword:
// Inside the Sensor class implementation:
void Sensor::readTemperature() {
double temp = readFromHardware();
emit temperatureChanged(temp); // Notify all connected slots
}
Slot
A slot is a function that can be connected to a signal. When the signal is emitted, the slot is called. Slots are declared with the public slots: (or private slots:, protected slots:) keyword.
class Display : public QObject {
Q_OBJECT
public slots:
void onTemperatureChanged(double temperature) {
qDebug() << "Temperature updated:" << temperature;
updateDisplay(temperature);
}
};
Slots are ordinary C++ functions that can also be called directly — the slots: keyword just marks them as connectable targets for MOC.
connect()
The connect() function links a signal to a slot. When the signal is emitted, the connected slot is automatically called.
connect(sender, signal, receiver, slot);
Syntax — Modern Qt 5/6 Style
Qt 5 introduced a new, type-safe connect syntax using function pointers. This is the recommended modern approach:
Sensor sensor;
Display display;
// Modern syntax: compile-time type checking
QObject::connect(&sensor, &Sensor::temperatureChanged,
&display, &Display::onTemperatureChanged);
Advantages of the modern syntax:
- Compile-time type safety — mismatched signal/slot parameter types are caught at compile time, not runtime
- Refactoring safe — renaming a signal or slot is caught by the compiler immediately
- IDE support — autocompletion works for signal and slot names
Syntax — Qt 4 Legacy Style (String-Based)
The original Qt 4 syntax used string macros:
// Legacy syntax (still valid but not recommended for new code)
QObject::connect(sender, SIGNAL(temperatureChanged(double)),
receiver, SLOT(onTemperatureChanged(double)));
This syntax still works, but errors in signal/slot names are only caught at runtime (printed to the debug output), not at compile time. Avoid it in new code.
Lambda Slots
Qt 5+ supports connecting signals to lambda functions — convenient for simple, inline responses:
QObject::connect(&sensor, &Sensor::temperatureChanged, [](double temp) {
qDebug() << "Lambda received temperature:" << temp;
});
Lambda slots are ideal when:
- The response is simple (a few lines of code)
- No separate slot method declaration is needed
- The slot logic is closely tied to the connect call and benefits from being inline
Many-to-Many Relationships
Signals and Slots support many-to-many connections — this is one of their most powerful characteristics:
Many-to-One:
[Signal A] ---|
[Signal B] ---+--> [Slot X]
[Signal C] ---|
One-to-Many:
|--> [Slot X]
[Signal A] --+--> [Slot Y]
|--> [Slot Z]
Many-to-Many:
[Signal A] ---| |--> [Slot X]
[Signal B] ---+--------->+--> [Slot Y]
[Signal C] ---| |--> [Slot Z]
- A single signal can be connected to multiple slots — all slots are called when the signal is emitted
- A single slot can be connected to multiple signals — the slot responds to any of the connected signals
- Signals can be connected to other signals — chaining signal propagation
Signal-to-Signal Connections
Signals can be connected to other signals, enabling event propagation without intermediate logic:
QPushButton button;
QDialog dialog;
// When button is clicked, emit dialog's accepted signal
QObject::connect(&button, &QPushButton::clicked,
&dialog, &QDialog::accepted);
This is useful for forwarding signals up through a component hierarchy without writing boilerplate forwarding slots.
Connection Types
Qt supports different connection types that control how the slot is called:
| Connection Type | Description | Use Case |
|---|---|---|
Qt::AutoConnection | Default; direct if same thread, queued if cross-thread | General use |
Qt::DirectConnection | Slot called synchronously in the sender's thread | Same-thread, immediate response |
Qt::QueuedConnection | Slot called asynchronously via the event loop | Cross-thread communication |
Qt::BlockingQueuedConnection | Like queued, but sender blocks until slot completes | Cross-thread with synchronization |
// Explicit cross-thread connection
QObject::connect(&workerThread, &Worker::resultReady,
&mainObject, &MainObject::handleResult,
Qt::QueuedConnection);
Disconnecting Signals and Slots
Connections can be severed explicitly with disconnect():
// Disconnect a specific connection
QObject::disconnect(&sensor, &Sensor::temperatureChanged,
&display, &Display::onTemperatureChanged);
// Disconnect all signals from a sender
QObject::disconnect(&sensor, nullptr, nullptr, nullptr);
Alternatively, connections are automatically cleaned up when either the sender or receiver object is destroyed — preventing dangling connections.
Using Qt Designer for Signal/Slot Connections
In Qt Designer (integrated in Qt Creator), signals and slots can be connected visually:
- Switch to Signals/Slots Mode in Qt Designer
- Drag from a widget (e.g., a button) to another widget (e.g., a dialog)
- Qt Designer shows available signals and slots and lets you connect them visually
- The connection is generated as C++ code in the
.uifile
This approach is useful for standard widget-to-widget connections without writing any code.
Practical Example — Button Click Counter
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
int clickCount = 0;
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QPushButton button("Click Me");
QLabel label("Clicks: 0");
layout.addWidget(&button);
layout.addWidget(&label);
// Connect button click signal to a lambda slot
QObject::connect(&button, &QPushButton::clicked, [&label]() {
clickCount++;
label.setText("Clicks: " + QString::number(clickCount));
});
window.show();
return app.exec();
}
Summary
| Concept | Description |
|---|---|
| Signal | A notification emitted when something happens (emit signalName()) |
| Slot | A function that responds to a connected signal |
| connect() | Links a signal to a slot (compile-time safe with modern syntax) |
| Many-to-many | One signal can connect to many slots; one slot can connect to many signals |
| Signal-to-signal | Signals can be chained together |
| Connection types | Auto, Direct, Queued — control synchronous vs. asynchronous execution |
| Auto-disconnect | Connections are removed automatically when objects are destroyed |
Signals and Slots is the heartbeat of Qt applications. Once you understand this mechanism, the architecture of every Qt application — from simple widgets to complex multi-threaded systems — becomes clear. It is the foundation for event handling, UI updates, inter-component communication, and thread-safe cross-object messaging.