In Qt, the signal-slot mechanism is a fundamental feature used for communication between objects. Sometimes, when a signal is emitted, you need to determine which object triggered the signal. This is particularly useful when multiple objects are connected to the same slot and need individual handling.
This topic explains how to retrieve the object that emitted a signal using different methods, with practical examples and best practices.
Understanding Qt’s Signal-Slot Mechanism
Qt’s signal-slot system allows objects to send notifications (signals) and respond (slots). However, when multiple objects emit the same signal, distinguishing between them is necessary.
Example of a basic signal-slot connection:
connect(button, &QPushButton::clicked, this, &MainWindow::handleClick);
In this case, when button
is clicked, the slot handleClick()
is executed. But what if multiple buttons are connected to the same slot? You need to identify which one was clicked.
Methods to Get the Object That Emitted a Signal
1. Using sender()
Method
Qt provides the QObject::sender()
method, which returns a pointer to the object that emitted the signal.
Example: Identifying the Button That Was Clicked
void MainWindow::handleClick() {QObject *object = sender(); // Get the sender objectif (object) {QPushButton *button = qobject_cast<QPushButton*>(object);if (button) {qDebug() << "Button clicked:" << button->text();}}}
Explanation
sender()
retrieves the object that emitted the signal.qobject_cast<QPushButton*>
ensures the object is of the correct type.button->text()
is used to identify the button by its label.
2. Using Lambda Functions with QObject::sender()
Instead of defining a separate slot function, you can use lambda expressions to access the sender object directly.
Example: Using a Lambda Function
connect(button, &QPushButton::clicked, this, [this]() {QPushButton *button = qobject_cast<QPushButton*>(sender());if (button) {qDebug() << "Button clicked:" << button->text();}});
3. Using QSignalMapper
for Multiple Objects
If you have multiple objects emitting the same signal, QSignalMapper
can help associate each sender with a unique value.
Example: Mapping Signals from Multiple Buttons
QSignalMapper *mapper = new QSignalMapper(this);QPushButton *button1 = new QPushButton("Button 1", this);QPushButton *button2 = new QPushButton("Button 2", this);connect(button1, SIGNAL(clicked()), mapper, SLOT(map()));connect(button2, SIGNAL(clicked()), mapper, SLOT(map()));mapper->setMapping(button1, "Button 1");mapper->setMapping(button2, "Button 2");connect(mapper, SIGNAL(mappedString(QString)), this, SLOT(handleMappedClick(QString)));void MainWindow::handleMappedClick(QString buttonName) {qDebug() << "Clicked:" << buttonName;}
Explanation
QSignalMapper
allows mapping each sender to a specific value.- The
mappedString(QString)
signal sends the associated string to the slot. - This method avoids using
sender()
and is more structured for handling multiple objects.
Best Practices When Using sender()
Although sender()
is useful, it should be used cautiously: