'How to connect in Qt signal and slot in dynamically added buttons to get in slot index of added button?

I have list with pointers QPushButton:

QList<QPushButton*> listButtons;

In this code I am adding dynamically buttons

listButtons.push_back(new QPushButton("Cancel", this)); 
connect(listButtons.last(), SIGNAL (clicked(listButtons.size)), this, SLOT(handleButton(int))); //this doesn't work

How can I also save index of every button, so I can keep track, what button user clicked, because every button has to cancel specific task.

I use C++98, so I can not use Lambda function



Solution 1:[1]

You have to use sender() function in your slot. like this:

void MainWindow::buttonClicked()
{
    QObject *senderObj = sender(); // This will give Sender object
    QString senderObjName = senderObj->objectName();
    qDebug()<< "Button: " << senderObjName;
}

See a complete example that i made for you: Screenshot

.cpp file:

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    for(int i =0; i<10; i++)
    {
        listButtons.push_back(createNewButton());
        connect(listButtons[i], &QPushButton::clicked, this, &MainWindow::buttonClicked);
        QString text = listButtons[i]->text();

        ui->widget->layout()->addWidget(listButtons[i]);
    }
}


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

QPushButton* MainWindow::createNewButton()
{
    QPushButton* button = new QPushButton("ButtonText");
    button->setObjectName("ButtonName");
    return button;
}

void MainWindow::buttonClicked()
{
    QObject *senderObj = sender(); // This will give Sender object
    QString senderObjName = senderObj->objectName();
    qDebug()<< "Button: " << senderObjName;
}

.h file:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QPushButton>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QList<QPushButton*> listButtons;

    QPushButton *createNewButton();
    void buttonClicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

More info:

sender() function returns a pointer to the object that sent the signal, if called in a slot activated by a signal; otherwise it returns 0. The pointer is valid only during the execution of the slot that calls this function from this object's thread context.

Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

Solution 2:[2]

An easy way to do that would be to capture the index (or whatever you want to pass to the slot) in a lambda connected to the signal that then pass it on to the slot.

The general idea being like so:

auto button = new QPushButton("Cancel", this);
auto index = /* code to get what you want to pass */ ;
connect(button, &QPushButton::clicked,
    this, [index, this](bool){ this->handleButton(index); });

Solution 3:[3]

You can refer to this page https://doc.qt.io/archives/qq/qq16-dynamicqobject.html.

Or looks up the implementation of QWebChannel. It maps Qt signal to the v8 environment, based on the above technology.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Kohill Yang