Handling Signal using QSignalMapper in Qt


Introduction

Qt is one of the best development frameworks in the software world. I’ve been using it for years and I’m still finding new things to learn. Some time back, I faced a situation that I need to call the same function with different value while clicking a group of buttons in my widget. Then I discovered QSignalMapper which let me tie a QString to a given action.
 
Handling signal using QSignalMapper in Qt

QSignalMapper Class

 The QSignalMapper class bundles signals from identifiable senders. This class collects a set of signals without parameter, and re-emits them with integer, string or widget parameters corresponding to the object that sent the signal.

The class supports the mapping of particular strings or integers with particular objects using setMapping(). The objects' signals can then be connected to the map() slot which will emit the mapped() signal with the string or integer associated with the original signalling object. Mappings can be removed later using removeMappings().

Understand with an example

Let us start with an example, consider I want to create a widget with some buttons (or any UI objects). One way is to connect each button’s ‘click’ signal with its own custom slot. In this case you need to create N number of custom slots even though the logic is same. QSignalMapper class plays a major role here, just we want to connect all the buttons to a single slot and parameterize the slot by the button that was clicked.

// creating the Signal Mapper object and connect custom slot to it.
QSignalMapper *bMapper = new QSignalMapper;
connect(bMapper, SIGNAL(mapped(QString)), this, SLOT(onClick(QString)));

// connect the UI object with signal mapper object and send the parameter to the slot
connect(ui->btnRed, SIGNAL(clicked()), bMapper, SLOT(map()));
bMapper->setMapping(ui->btnRed, "Red");


Let us analyse the above code in detail. First create the object for QSignalMapper class and connect your own slot (let’s say onClick) with parameter. It supports integer, QString, QWidget and QObject parameters. Now we have ready with customized signal mapped with our own slot. We can connect this signal mapper to any UI signals and send the appropriate parameters.

mainwindow.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include <QSignalMapper>
#include <QMessageBox>
 

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 

    // creating the Signal Mapper object and connect custom slot to it.
    QSignalMapper *bMapper = new QSignalMapper;
    connect(bMapper, SIGNAL(mapped(QString)), this, SLOT(onClick(QString)));
 

    // connect the UI object with signal mapper object and send the parameter to the slot
    connect(ui->btnRed, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnRed, "Red");
  

    connect(ui->btnBlue, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnBlue, "Blue");
 

    connect(ui->btnYellow, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnYellow, "Yellow");
 

    connect(ui->btnBlack, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnBlack, "Black");
 

    connect(ui->btnGreen, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnGreen, "Green");
 

    connect(ui->btnWhite, SIGNAL(clicked(bool)), bMapper, SLOT(map()));
    bMapper->setMapping(ui->btnWhite, "White");
}
 

MainWindow::~MainWindow()
{
    delete ui;
}
 

void MainWindow::onClick(QString color) {

    QMessageBox::information(this, tr("Colour Information"),
                             tr("%1 button pressed.")
                             .arg(color));

}


mainwindow.h


#ifdef  MAINWINDOW_H
#define MAINWINDOW_H
 

#include <QMainWindow>
 

namespace Ui {
class MainWindow;
}
 

class MainWindow : public QMainWindow
{
    Q_OBJECT
 

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 

private:
    Ui::MainWindow *ui;
 

private slots:
    void onClick(QString);
};

#endif // MAINWINDOW_H


Hope you found it useful. Please let me know!


1 comments:

Helped me a lot. Thank you sir.