从 uic 输出到 Qt 中的 C++ 代码

Posted

技术标签:

【中文标题】从 uic 输出到 Qt 中的 C++ 代码【英文标题】:From uic output to C++ code in Qt 【发布时间】:2016-09-24 10:54:39 【问题描述】:

为了更好地学习 Qt,我想了解 如何使用 Qt 的 User Interface Compiler 的 C++ 头文件输出以编程方式重新创建相同的 UI 设计(例如使用 Qt Creator 中的 Designer 派生的那个)。

我应该在我的 Qt 项目中创建一个新的头文件并复制那个 uic 输出的内容吗? uic 输出中的哪些部分去哪里以及如何在.cpp 中调用它们?

这是在良好编程实践方面的最佳方法;对意见不感兴趣,只对如何正确分离定义并按原样使用头文件和源文件感兴趣?

在哪里/如何定义布局和小部件以及如何调用/自定义它们(可能在 .cpp 文件中?)的最小示例对我来说是一个很好的学习工具。

作为示例,下面是一个使用 Qt Creator 的设计器工具创建的 GUI 设计示例,其中包含多个嵌套布局和多个小部件:

这是上述 GUI 设计的 uic 头文件输出:

#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

(这个问题基本上是我previous问题的后续)

【问题讨论】:

“就良好的编程实践而言,这是最佳方法吗”? 否。尝试将uic 和/或moc 的输出作为标题包含在内等等不是要走的路。这些自动生成的文件应该单独放置。 @ray 这也是我的第一印象。但是,我仍然希望能够以编程方式重新创建在 Designer 中看到的 GUI(理想情况下,利用良好的实践,而不是将所有内容都转储到 .cpp)。我认为也许 uic 输出可以用作创建头文件和源文件的起点。如果您能展示代码来实现这一点,我将不胜感激。 “为了更好地学习 Qt,我想学习” - 那么阅读和理解输出有什么问题呢?无需编写任何代码,或重复使用自动生成的代码。 @nk-fford。如果uic 的输出不满足您的要求,有几十个example programs in the qt docs 可能会这样做。 @iinspectable 没有错,实际上我确实研究了输出。我的缺点真的是如何以编程方式设计一个 qt gui;缺乏在线资源让我来到这里,希望我能看到一个完整的示例代码。 【参考方案1】:

最好的方法是使用生成的类作为适当的小部件类的成员,在您的情况下作为QMainWindow 派生类的成员:

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;
;

然后在源文件中创建一个实例

#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;

这也是QtCreator模板为“New Designer Form Class”生成的结构。

【讨论】:

以上是关于从 uic 输出到 Qt 中的 C++ 代码的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 c && 调用 c++ 函数将应用程序输出重定向到 Qt 中的 textEdit

在qt c++中获取Json数组中Qstring的输出

信号和槽:Qt中最差劲的创造

在 Visual Studio 中将自定义代码添加到 Qt UIC 生成的文件

用户界面编译器 (Uic) qt3 与 qt4/5,impl 参数等价

如何使用 setupUi 或 uic 输出来创建没有父小部件的独立布局?