C0deGyver
C0deGyver

Reputation: 49

How to dynamically add QPushButtons to UI

FYI I am using Qt Creator 3.3.2 on Linux Mint.

Okay first I would like to admit I have seen a few questions very similar to the one I am asking... Such as How to add a widget (QPushButton for example) dynamically to a layout built in designer. However (for whatever reason) I have had no success in either understanding the answer or implementing it. I am extremely new to Qt and this is my first project in it so please be through so I can understand the answer.

What I have so far: The UI: I have a scroll area named srcFolderPairSelect and under that (in the 'object' window) I have a scroll contents named scrLayFolderPairSelect. In a different section/area (different frame and layout) I have a button that is to add a button, to the before mentioned scroll contents, named btnAddNewFolderPair, upon click. PS: I need it to be able to be clicked more than once (need to be able to add multiple dynamic buttons to the scroll contents).

The header file:

#ifndef SYNCCENTER_H
#define SYNCCENTER_H

#include <QMainWindow>

namespace Ui {
    class SyncCenter;
}

class SyncCenter : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_btnAddFolderPair_clicked();

private:
    Ui::SyncCenter *ui;
};

#endif // SYNCCENTER_H

The UI cpp (synccenter.cpp):

#include "synccenter.h"
#include "ui_synccenter.h"

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

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

void SyncCenter::on_btnAddFolderPair_clicked()
{
    QPushButton* button = new QPushButton("test");
    button->setVisible(true);
    ui->scrLayFolderPairSelect->layout()->addWidget(button);
}

Also how do I form onclick events for the dynamic buttons?

Upvotes: 4

Views: 3587

Answers (1)

VP.
VP.

Reputation: 16705

In a very fast way you can do it like this:

void SyncCenter::on_btnAddFolderPair_clicked()
{
    static int count{};
    QPushButton* button = new QPushButton(QString("test %1").arg(++count), this);
    button->setVisible(true);
    connect(button, &QPushButton::clicked, [&count](){
        std::cout << "Clicked button number: " << count << std::endl;
    });
    ui->scrLayFolderPairSelect->layout()->addWidget(button);
}

The main idea is to store slots(handlers), then, if you need - store buttons itselves.

This my "very fast" solution is based on not a good way of implementing this.

You have a lot of ways of implementing this, however, I think, the best solution is to create QButtonGroup because it has a signals such as:

void buttonClicked(QAbstractButton *button);
void buttonClicked(int id);

So, your code will be like:

class SyncCenter {
    //....
private slots:
    void buttonInGroupClicked(QAbstractButton *);

private:    
    QButtonGroup *buttonGroup;
};

SyncCenter::SyncCenter(/*...*/) {
    buttonGroup = new QButtonGroup(this);
    connect(buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(buttonInGroupClicked(QAbstractButton*)));
}

void SyncCenter::buttonInGroupClicked(QAbstractButton *b) {
    // do anything with your button
}

void SyncCenter::on_btnAddFolderPair_clicked()
{
    static int count{};
    QPushButton* button = new QPushButton(QString("test %1").arg(++count), this);
    button->setVisible(true);
    buttonGroup->addButton(button);
    ui->scrLayFolderPairSelect->layout()->addWidget(button);
}

Upvotes: 5

Related Questions