0

In the interest of better learning Qt, I would like to learn how it would be possible to use the C++ header file output of Qt's User Interface Compiler to programmatically recreate the same UI design (e.g. as the one derived by using the Designer in Qt Creator).

Should I create a new header file in my Qt project and copy the contents of that uic output? Which parts from the uic ouptut go where and how should I call them in the .cpp?

Is this best approach in terms of good programming practices; not interested in opinions, only on how to properly separate definitions and use the header and source files as they are meant to?

A minimal example of where/how to define the layouts and widgets and how to invoke/customise them (perhaps in the .cpp file?) would be a great learning tool for me.

As an example, here is an example of a GUI design created with the Qt Creator's Designer tool with several nested layouts and multiple widgets:

enter image description here

enter image description here

enter image description here

And this is the header file ouptut from the uic for the above GUI design:

#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QFrame>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QProgressBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
    QWidget *centralWidget;
    QVBoxLayout *verticalLayout_3;
    QFrame *top_frame;
    QGridLayout *gridLayout;
    QSpacerItem *horizontalSpacer;
    QProgressBar *progressBar_2;
    QProgressBar *progressBar_4;
    QSpacerItem *verticalSpacer;
    QSpacerItem *horizontalSpacer_2;
    QPushButton *pushButton_1;
    QProgressBar *progressBar_1;
    QPushButton *pushButton_2;
    QPushButton *pushButton_3;
    QProgressBar *progressBar_3;
    QPushButton *pushButton_4;
    QFrame *bottom_frame;
    QHBoxLayout *horizontalLayout;
    QFrame *frame;
    QFormLayout *formLayout;
    QLabel *label_1;
    QLabel *label_2;
    QSpacerItem *verticalSpacer_2;
    QLineEdit *lineEdit;
    QLineEdit *lineEdit_2;
    QFrame *frame_2;
    QHBoxLayout *horizontalLayout_2;
    QLabel *label_3;
    QSpacerItem *horizontalSpacer_3;
    QLabel *label_4;

    void setupUi(QMainWindow *MainWindow)
    {
        if (MainWindow->objectName().isEmpty())
            MainWindow->setObjectName(QStringLiteral("MainWindow"));
        MainWindow->resize(878, 632);
        centralWidget = new QWidget(MainWindow);
        centralWidget->setObjectName(QStringLiteral("centralWidget"));
        verticalLayout_3 = new QVBoxLayout(centralWidget);
        verticalLayout_3->setSpacing(6);
        verticalLayout_3->setContentsMargins(11, 11, 11, 11);
        verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3"));
        top_frame = new QFrame(centralWidget);
        top_frame->setObjectName(QStringLiteral("top_frame"));
        QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
        sizePolicy.setHorizontalStretch(0);
        sizePolicy.setVerticalStretch(0);
        sizePolicy.setHeightForWidth(top_frame->sizePolicy().hasHeightForWidth());
        top_frame->setSizePolicy(sizePolicy);
        top_frame->setFrameShape(QFrame::StyledPanel);
        top_frame->setFrameShadow(QFrame::Raised);
        gridLayout = new QGridLayout(top_frame);
        gridLayout->setSpacing(6);
        gridLayout->setContentsMargins(11, 11, 11, 11);
        gridLayout->setObjectName(QStringLiteral("gridLayout"));
        horizontalSpacer = new QSpacerItem(30, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);

        gridLayout->addItem(horizontalSpacer, 0, 2, 1, 1);

        progressBar_2 = new QProgressBar(top_frame);
        progressBar_2->setObjectName(QStringLiteral("progressBar_2"));
        progressBar_2->setValue(24);

        gridLayout->addWidget(progressBar_2, 2, 3, 1, 1);

        progressBar_4 = new QProgressBar(top_frame);
        progressBar_4->setObjectName(QStringLiteral("progressBar_4"));
        progressBar_4->setValue(24);

        gridLayout->addWidget(progressBar_4, 2, 5, 1, 1);

        verticalSpacer = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed);

        gridLayout->addItem(verticalSpacer, 1, 1, 1, 1);

        horizontalSpacer_2 = new QSpacerItem(10, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);

        gridLayout->addItem(horizontalSpacer_2, 0, 4, 1, 1);

        pushButton_1 = new QPushButton(top_frame);
        pushButton_1->setObjectName(QStringLiteral("pushButton_1"));

        gridLayout->addWidget(pushButton_1, 0, 0, 1, 1);

        progressBar_1 = new QProgressBar(top_frame);
        progressBar_1->setObjectName(QStringLiteral("progressBar_1"));
        progressBar_1->setValue(24);

        gridLayout->addWidget(progressBar_1, 0, 3, 1, 1);

        pushButton_2 = new QPushButton(top_frame);
        pushButton_2->setObjectName(QStringLiteral("pushButton_2"));

        gridLayout->addWidget(pushButton_2, 0, 1, 1, 1);

        pushButton_3 = new QPushButton(top_frame);
        pushButton_3->setObjectName(QStringLiteral("pushButton_3"));

        gridLayout->addWidget(pushButton_3, 2, 0, 1, 1);

        progressBar_3 = new QProgressBar(top_frame);
        progressBar_3->setObjectName(QStringLiteral("progressBar_3"));
        progressBar_3->setValue(24);

        gridLayout->addWidget(progressBar_3, 0, 5, 1, 1);

        pushButton_4 = new QPushButton(top_frame);
        pushButton_4->setObjectName(QStringLiteral("pushButton_4"));

        gridLayout->addWidget(pushButton_4, 2, 1, 1, 1);


        verticalLayout_3->addWidget(top_frame);

        bottom_frame = new QFrame(centralWidget);
        bottom_frame->setObjectName(QStringLiteral("bottom_frame"));
        bottom_frame->setFrameShape(QFrame::StyledPanel);
        bottom_frame->setFrameShadow(QFrame::Raised);
        horizontalLayout = new QHBoxLayout(bottom_frame);
        horizontalLayout->setSpacing(6);
        horizontalLayout->setContentsMargins(11, 11, 11, 11);
        horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
        frame = new QFrame(bottom_frame);
        frame->setObjectName(QStringLiteral("frame"));
        frame->setFrameShape(QFrame::StyledPanel);
        frame->setFrameShadow(QFrame::Raised);
        formLayout = new QFormLayout(frame);
        formLayout->setSpacing(6);
        formLayout->setContentsMargins(11, 11, 11, 11);
        formLayout->setObjectName(QStringLiteral("formLayout"));
        label_1 = new QLabel(frame);
        label_1->setObjectName(QStringLiteral("label_1"));

        formLayout->setWidget(0, QFormLayout::LabelRole, label_1);

        label_2 = new QLabel(frame);
        label_2->setObjectName(QStringLiteral("label_2"));

        formLayout->setWidget(1, QFormLayout::LabelRole, label_2);

        verticalSpacer_2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);

        formLayout->setItem(2, QFormLayout::LabelRole, verticalSpacer_2);

        lineEdit = new QLineEdit(frame);
        lineEdit->setObjectName(QStringLiteral("lineEdit"));
        QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding);
        sizePolicy1.setHorizontalStretch(0);
        sizePolicy1.setVerticalStretch(0);
        sizePolicy1.setHeightForWidth(lineEdit->sizePolicy().hasHeightForWidth());
        lineEdit->setSizePolicy(sizePolicy1);

        formLayout->setWidget(3, QFormLayout::SpanningRole, lineEdit);

        lineEdit_2 = new QLineEdit(frame);
        lineEdit_2->setObjectName(QStringLiteral("lineEdit_2"));
        sizePolicy1.setHeightForWidth(lineEdit_2->sizePolicy().hasHeightForWidth());
        lineEdit_2->setSizePolicy(sizePolicy1);

        formLayout->setWidget(4, QFormLayout::LabelRole, lineEdit_2);


        horizontalLayout->addWidget(frame);

        frame_2 = new QFrame(bottom_frame);
        frame_2->setObjectName(QStringLiteral("frame_2"));
        frame_2->setFrameShape(QFrame::StyledPanel);
        frame_2->setFrameShadow(QFrame::Raised);
        horizontalLayout_2 = new QHBoxLayout(frame_2);
        horizontalLayout_2->setSpacing(6);
        horizontalLayout_2->setContentsMargins(11, 11, 11, 11);
        horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
        label_3 = new QLabel(frame_2);
        label_3->setObjectName(QStringLiteral("label_3"));

        horizontalLayout_2->addWidget(label_3);

        horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);

        horizontalLayout_2->addItem(horizontalSpacer_3);

        label_4 = new QLabel(frame_2);
        label_4->setObjectName(QStringLiteral("label_4"));

        horizontalLayout_2->addWidget(label_4);

        frame->raise();
        frame->raise();
        label_3->raise();
        label_4->raise();

        horizontalLayout->addWidget(frame_2);


        verticalLayout_3->addWidget(bottom_frame);

        MainWindow->setCentralWidget(centralWidget);

        retranslateUi(MainWindow);

        QMetaObject::connectSlotsByName(MainWindow);
    } // setupUi

    void retranslateUi(QMainWindow *MainWindow)
    {
        MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
        pushButton_1->setText(QApplication::translate("MainWindow", "PushButton_1", 0));
        pushButton_2->setText(QApplication::translate("MainWindow", "PushButton_2", 0));
        pushButton_3->setText(QApplication::translate("MainWindow", "PushButton_3", 0));
        pushButton_4->setText(QApplication::translate("MainWindow", "PushButton_4", 0));
        label_1->setText(QApplication::translate("MainWindow", "TextLabel_1", 0));
        label_2->setText(QApplication::translate("MainWindow", "TextLabel_2", 0));
        label_3->setText(QApplication::translate("MainWindow", "TextLabel_3", 0));
        label_4->setText(QApplication::translate("MainWindow", "TextLabel_4", 0));
    } // retranslateUi

};

namespace Ui {
    class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MAINWINDOW_H

(this question is -basically- a follow-up from my previous question)

Community
  • 1
  • 1
  • 1
    *"Is this best approach in terms of good programming practices"?* No. Trying to include the `uic`'s and/or `moc`'s output as headers and so on isn't the way to go. Those auto-generated files are meant to be left alone. – code_dredd Sep 24 '16 at 11:09
  • @ray That was my first impression as well. But, still, I would like to be able to programmatically recreate a GUI as seen at the Designer (ideally, utilising good practices and not dump everything in `.cpp`). I thought that perhaps the uic output could be used as a starting point to create the header and source files. If you could show code to achieve this I would really appreciate it. –  Sep 24 '16 at 11:25
  • 1
    *"In the interest of better learning Qt, I would like to learn"* - What's wrong with reading and comprehending the output then? There's no need to write any code, or re-use auto-generated code. – IInspectable Sep 24 '16 at 12:36
  • @nk-fford. If the output of `uic` somehow doesn't satisfy your requirements, there are dozens of [example programs in the qt docs](http://doc.qt.io/qt-5/qtexamplesandtutorials.html) that may do so. – ekhumoro Sep 24 '16 at 12:56
  • @iinspectable Nothing wrong with that, actually I did study the output. My shortcoming is really how to programmatically design a qt gui; lack of online resources led me here in the hopes I would see a full example code of exactly that. –  Sep 24 '16 at 12:56
  • Start with a **minimal** example. Expand on that. – Cheers and hth. - Alf Sep 24 '16 at 13:08
  • @Cheersandhth.-Alf I am searching for online resources with a relatively complex nested layout and multiple widgets; in the meantime, if it is easy for you to give an answer demonstrating such an example (perhaps, even for the example I provide in my descritpion above) that would be great for to get started. –  Sep 24 '16 at 13:20
  • @nk-fford: I'm sorry but (1) I don't have Qt installed and I don't plan on installing it, and (2) it's *you* who need to learn from doing the minimal example, not readers of SO, who probably can't easily communicate what they learned about it short of writing a longish tutorial, which SO isn't about. – Cheers and hth. - Alf Sep 24 '16 at 13:23
  • @Cheersandhth.-Alf (1) lol (2) Fiar point, but I merely asked for suggestions / guidance / point to resources which I may be missing. If someone would also give an answer with an example, then that would certainly help my studying of the subject. Examples *DO* and *SHOULD* be how SO communicate. Apologies if I showed that I was bored to do my own research and study; that is not the case. –  Sep 24 '16 at 13:27
  • @nk-fford. What do you find lacking in the numerous example programs provided in the qt docs? – ekhumoro Sep 24 '16 at 15:49

1 Answers1

0

The best way is to use the generated class as a member of an appropriate widget class, in your case as a member of a QMainWindow derived class:

namespace Ui {
    class MainWindow; // forward declaration of the generated class
}

class MyMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MyMainWindow(QWidget *parent = 0);
    ~MyMainWindow();

private:
    Ui::MainWindow *ui;
};

You then create an instance of that inside the source file

#include "ui_mainwindow.h" // include the generated header

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this); // let the generate class populate "this"
}

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

This is also the structure generated by the QtCreator template for "New Designer Form Class".

Kevin Krammer
  • 5,159
  • 2
  • 9
  • 22