Generating widgets dynamically
-
Hello. Up to this point I have been using widget.ui to generate widgets, assign slots to them. It was very convenient and easy to do but I have got to the point in my project where I need to create custom widgets programmatically based on user choice.
In my QT application, there is a QComboBox that allows user to select from a few different options:
When user selects one of the available options, a function in my program will be triggered:
void Widget::on_Scenario_select_currentIndexChanged(int index) { qDebug("scenario selected =%s \n",ui->Scenario_select->currentText().toStdString().c_str()); // if user selects Option1, generate QScrollArea and inside that area generate 4 Radio Buttons // if user selects Option2, generate QScrollArea and inside that are generate 6 Radio Buttons. }
For example, when user selects Option1, it I need to generate the following widgets:
Could someone clarify to me how can this be done as I havent managed to find an easy example
-
@lukutis222 Well, you could do all this in designer: use https://doc.qt.io/qt-6/qstackedwidget.html Using it you can create several "pages" with widgets and then simply show one of these pages based on user selection.
Creating widgets dinamically is easy. To see how it is done you can take a look at auto-generated code (ui_xxx.h files). Also there are many examples in Qt documentation.
-
@jsulm
Thanks for quick reply. The first option that you have suggested is not good idea for my particular example because there will be many different options available (I just show you example of 2 options) so I much rather generate ir programmatically.I have tried this so far:
void Widget::on_Scenario_select_currentIndexChanged(int index) { qDebug("scenario selected =%s \n",ui->Scenario_select->currentText().toStdString().c_str()); // if user selects Option1, generate if(ui->Scenario_select->currentText().toStdString()=="Option1"){ qDebug("Option1 selected \n"); QScrollArea scrollArea; scrollArea.setBackgroundRole(QPalette::Dark); scrollArea.show(); } }
The code above will create a scroll area and I can see it show up on my screen for a brief moment and then it dissapears immediately.
Can you clarify where can I find the auto-generated code that you mentioned? In my project, I only see the following files:
-
@lukutis222 said in Generating widgets dynamically:
QScrollArea scrollArea;
This can't work, because scrollArea is alocal variable which is destroyed as soon as on_Scenario_select_currentIndexChanged finishes. Create widgets on the heap, not stack.
-
@jsulm
Thanks for clarifying.I have created testtool.cpp and testtool.h files where I want to keep all functions for creating custom widgets.
testtool.h:
#ifndef TESTTOOL_H #define TESTTOOL_H #include <QWidget> #include <QListView> #include <QScrollArea> #include <QRadioButton> class TestTool : public QWidget { Q_OBJECT public: explicit TestTool(QWidget *parent = nullptr); void Create_widgets(); private: QScrollArea *scrollArea; QWidget *scrollAreaWidgetContents; QRadioButton *radioButton; QRadioButton *radioButton_2; QRadioButton *radioButton_3; QRadioButton *radioButton_4; signals: }; #endif // TESTTOOL_H
testtool.cpp
#include "testtool.h" TestTool::TestTool(QWidget *parent) : QWidget{parent} { } void TestTool::Create_widgets(){ scrollArea = new QScrollArea(); scrollArea->setObjectName(QString::fromUtf8("scrollArea")); scrollArea->setGeometry(QRect(30, 80, 481, 371)); scrollArea->setWidgetResizable(true); scrollArea->show(); }
In my widget.cpp I create a class object for the testtool:
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) , serial(new Serial) , file(new Logging) , test_tool_object(new TestTool)
I use test_too_object to be able to call methods that are described in the testtool.
As you can see I have only one method in testtool:
void TestTool::Create_widgets(){ scrollArea = new QScrollArea(); scrollArea->setObjectName(QString::fromUtf8("scrollArea")); scrollArea->setGeometry(QRect(30, 80, 481, 371)); scrollArea->setWidgetResizable(true); scrollArea->show(); }
And I call this method when the scenario option is selected:
void Widget::on_Scenario_select_currentIndexChanged(int index) { qDebug("scenario selected =%s \n",ui->Scenario_select->currentText().toStdString().c_str()); // if user selects Option1, generate if(ui->Scenario_select->currentText().toStdString()=="Option1"){ qDebug("Option1 selected \n"); //Create_widgets test_tool_object->Create_widgets(); } }
However, when I selection "Option1" the qscrollarea is create but it is not linked with my main widget. Is that because I have not set it to be a child for my main widget?
-
@lukutis222 said in Generating widgets dynamically:
Is that because I have not set it to be a child for my main widget?
yes