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?
-
Did you ever manage to create something dynamically in `c++` ? – VP. Sep 03 '15 at 07:27
-
you need to create an event with signals and slots – Megasa3 Sep 03 '15 at 07:39
-
I put a listwidget and insert filenames in it dynamically. @victorpolevoy. So, should I write a slot function in c++ or did you mention something different? Also which event type should I make? – Enes Altuncu Sep 03 '15 at 07:42
-
All you need is just to create widgets dynamically in `c++` code and put them into same parent widget. You have a lot of ways of achieving this. – VP. Sep 03 '15 at 07:43
-
But how can I arrange the place of the widgets because I want to add new widget under another widget? – Enes Altuncu Sep 03 '15 at 07:46
-
@qwerty use layouts. – VP. Sep 03 '15 at 07:52
-
How should I use layouts? I'm quite new in Qt. Sorry for inconvenience. – Enes Altuncu Sep 03 '15 at 07:59
-
@qwerty [see this](http://doc.qt.io/qt-5/examples-layouts.html) – VP. Sep 03 '15 at 08:16
1 Answers
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.

- 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