2

I have a groupbox that contains some pushbuttons and sliders. I want that when I click on a button, a new groupbox that is the same with the former one should appear under the first one. Whenever I click on the button, same situation should happen dynamically. Since I need up to 32 groupbox like that, I don't want to put all groupboxes manually. So, how can I do this?

Enes Altuncu
  • 449
  • 2
  • 7
  • 14

1 Answers1

2

First off, a layout is highly recommended.

Here is an example (I have done this before). You can derive a class from QScrollArea, then set in the constructor the layouts you want to have.

In here a simple button called Add is in the window. If you press it, a row gets added and initialized with default values (0, 0, 0) <- integers. In the live program, I load the values from a file/database and initialize it then.

You may want to use different layout(s) and a different setup, but this should give you the idea. I'm sure you get where you want with a little more experimenting.

//Structure to keep track of the added widgets easier
struct ItemRow
{
    ItemRow(QLineEdit *entry, QLineEdit *amount, QComboBox *box)
        : m_Entry(entry)
        , m_Amount(amount)
        , m_Box(box)
    { }

    ItemRow(void)
        : m_Entry(nullptr)
        , m_Amount(nullptr)
        , m_Box(nullptr)
    { }

    QLineEdit *m_Entry;
    QLineEdit *m_Amount;
    QComboBox *m_Box;
};

The class declaration.

class MyScrollArea : public QScrollArea
{
    Q_OBJECT

public:
    explicit MyScrollArea(QWidget *parent = 0);
    ~MyScrollArea();
    //...
    void OnAddButtonPressed(void);
    void DrawButtonLayout(void);
    void AddRow(int val1, int val2, int val3); //Use own parameters

private:
    QVBoxLayout *m_LayoutFirstRow;
    QVBoxLayout *m_LayoutSecondRow;
    QVBoxLayout *m_LayoutThirdRow;
    //...
    QVBoxLayout *m_LayoutButton;
    //...
    QList<QPushButton*> m_Buttons;
    QVector<ItemRow> m_ItemRows;
}

The implementation.

MyScrollArea::MyScrollArea(QWidget *parent) :
    QScrollArea(parent),
    ui(new Ui::MyScrollArea)
{
    ui->setupUi(this);
    setWidget(new QWidget);
    setWidgetResizable(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

    QHBoxLayout *mainLayout = new QHBoxLayout(this);

    m_LayoutFirstRow    = new QVBoxLayout();
    m_LayoutSecondRow   = new QVBoxLayout();
    m_LayoutThirdRow    = new QVBoxLayout();
    m_LayoutButton      = new QVBoxLayout();

    widget()->setLayout(mainLayout);

    mainLayout->addLayout(m_LayoutFirstRow);
    mainLayout->addLayout(m_LayoutSecondRow);
    mainLayout->addLayout(m_LayoutThirdRow);
    mainLayout->addLayout(m_LayoutButton);

    DrawButtonLayout();
}

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

void MyScrollArea::OnAddButtonPressed(void)
{
    AddRow(0, 0, 0);
}

void MyScrollArea::DrawButtonLayout(void)
{
    QPushButton *addBtn = new QPushButton("Add");
    connect(addBtn, SIGNAL(clicked()), this, SLOT(OnAddButtonPressed()));
    m_LayoutButton->addWidget(addBtn);
    m_Buttons.push_back(addBtn); //Keep somewhere track of the button(s) if needed - example: put in QList (not the best approach though)
}

void MyScrollArea::AddRow(int val1, int val2, int val3)
{
    QLineEdit *pEntry = new QLineEdit(QString::number(val1));
    pEntry->setValidator(new QIntValidator());
    QLineEdit *pAmount = new QLineEdit(QString::number(val2));
    pAmount->setValidator(new QIntValidator());
    QComboBox *pBox = new QComboBox();
    InitComboBox(pBox, val3); //Initialize the combo-box (use connect if you wish) - code not included

    m_LayoutFirstRow->addWidget(pEntry);
    m_LayoutSecondRow->addWidget(pAmount);
    m_LayoutThirdRow->addWidget(pBox);

    ItemRow row;
    row.m_Entry = pEntry;
    row.m_Amount = pAmount;
    row.m_Box = pBox;
    m_ItemRows.push_back(row);
}

Leave a comment if something seems wrong, I put this together in Notepad++.

Note: The documentation-link is for QT4.8, as 5.3 is not available anymore, but my code is from version 5.3 too.

Blacktempel
  • 3,935
  • 3
  • 29
  • 53
  • I have understood but I have one more question. I have a groupbox contains some sliders and buttons. When I add new groupbox dynamically, should I add all sliders and buttons manually or is there any better solution to do that? – Enes Altuncu Sep 03 '15 at 12:32
  • Simply make a function like I did `AddRow` or name it `AddGroupBox` and handle adding a new group-box plus controls inside in the function. So you have to do outside only a simple call to the add function. (With or without parameters, it's your decision) You *could* add a layout in the group-box too. – Blacktempel Sep 04 '15 at 05:30
  • Thank you for your good solution. Then, this is the last question. I put a layout and then a scroll area. But firstly my groupbox covers all layout, then whenever I add a new groupbox, the size of them is decreasing and there is no scroll bar still. What can be the problem? – Enes Altuncu Sep 04 '15 at 11:27
  • Did you use `setWidgetResizable` and set the size policy of it ? Otherwise it won't expand. – Blacktempel Sep 07 '15 at 04:35
  • I turned setwidgetresizable to on and set the size policy to preferred. Is it true or should I set them to something else? – Enes Altuncu Sep 10 '15 at 13:41
  • Class definition should be ended with semicolon (I cannot edit the post because of 6 characters limit. I will remove my comment after it is edited). – Lati Feb 25 '19 at 07:52