Executing dynamically created buttons

1.6k views Asked by At

In my qt c++ application I create buttons dynamically based on the contents of a QStringList(i.e number of buttons is equal to the number of elements in the QStringlist and the text of the buttons are the elements in the list).

following is my code

#include "dialog.h"
#include "ui_dialog.h"
#include "QFrame"
#include "QLabel"
#include "QPushButton"

Dialog::Dialog(QWidget *parent) :
QDialog(parent),

ui(new Ui::Dialog)
{
    ui->setupUi(this);

}

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

void Dialog::createButtons(){

    List<<"Run"<<"Stop"";

    for(int i=0;i<List.size();i++){
        f1 = new QFrame();
        a= new QPushButton();
        a->setText(List[i]);
        ui->horizontalLayout->addWidget(a);
    }
}

void Dialog::Run(){
     qDebug() << "You clicked on the Run button";
}

void Dialog::Stop(){
     qDebug() << "You clicked on the Stop button";

}

void Dialog::on_pushButton_clicked()
{
    createButtons()        
}

Here "List"is the respective QStringList that I used!

when I call the createButtons() method in a button click as shown in my code the buttons are dynamically created!

The buttons are displaying the names of elements in the qstringlist! Each element has a method name! so when I click a button a method resembling that method name should get executed!

In this scenario 2 buttons are created displaying "Run"and "Stop". when I click the button displaying "Run"I want to execute the Run() method defined above!

How can I achieve it?

1

There are 1 answers

9
eyllanesc On BEST ANSWER

A possible solution is to use QMetaObject::invokeMethod(), but for this it is necessary that the Run and Stop functions must be slots:

private slots:
    void on_pushButton_clicked();
    // slots of button
    void onClicked();
    // your functions
    void Run();
    void Stop();

To do this we connect the buttons to the onClicked slot:

void Dialog::createButtons()
{
    List<<"Run"<<"Stop";
    for(const QString &text : List ){
        QPushButton* a= new QPushButton(this);
        a->setText(text);
        ui->horizontalLayout->addWidget(a);
        connect(a, &QPushButton::clicked, this, &Dialog::onClicked);
    }
}

And then through sender() you get the button that issued the signal, and therefore you get the text:

void Dialog::onClicked()
{
    QPushButton *b = qobject_cast<QPushButton *>(sender());
    QMetaObject::invokeMethod(this, b->text().toLatin1().data());
}

The complete example can be found in the following link.

with QSignalMapper:

.h

private slots:
    void on_pushButton_clicked();
    void Run();
    void Stop();
    void onClicked(const QString &text);
private:
    QSignalMapper *signalMapper;

.cpp

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    signalMapper = new QSignalMapper(this);
}

void Dialog::createButtons()
{
    List<<"Run"<<"Stop";
    for(const QString &text : List ){
        QPushButton* a= new QPushButton(this);
        a->setText(text);
        ui->horizontalLayout->addWidget(a);
        connect(a, &QAbstractButton::clicked, signalMapper, QOverload<>::of(&QSignalMapper::map));
        signalMapper->setMapping(a, text);
    }

    connect(signalMapper, QOverload<const QString &>::of(&QSignalMapper::mapped), this, &Dialog::onClicked);
}

void Dialog::onClicked(const QString &text)
{
    QMetaObject::invokeMethod(this, text.toLatin1().data());
}