写了很久QT 代码, 忽然对ui 到底是什么有了疑惑, 干脆认真研究一下ui 吧.
用QtCreator 点几下鼠标生成一个标准的QMainWindow 框架程序. 先来看看主要程序
$ cat mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
ui 是什么? ui 看起来是一个Ui::MainWindow 对象指针. 那Ui::MainWindow 又是什么呢?
且慢,再看看mainwindow.h 吧.
$ cat mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
//QT_BEGIN_NAMESPACE // qt_begin_namespace 及 qt_end_namespace 这两个宏展开后为空,故也可以注释掉.
namespace Ui { class MainWindow; } //声明一个Ui空间的MainWindow类 注释该行, 会使19行出现: error: ‘Ui’ does not name a type
//QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
头文件中说明, ui 是一个Ui::MainWindow 的指针, 同时也说明Ui 是一个命名空间, 它下面有一个类叫MainWindow.
至于QT_BEGIN_NAMESPACE, QT_END_NAMESPACE 是2个空得宏, 仅起标识作用. 代码上已经注释了关键点.
又回到上个关键点: Ui::MainWindow 又具体是什么样子呢?
这是在ui_mainwindow.h 中定义的. 就是由mainwindow.ui 生成的头文件.
$ cat ui_mainwindow.h
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.14.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralwidget;
QMenuBar *menubar;
QStatusBar *statusbar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(800, 600);
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
从这个文件可以看出, Ui::MainWindow 类是Ui_MainWindow 的子类. 它公有继承于父类.
从而也继承了父类的2个函数setupUi, retranslateUi及其父类个各个对象指针. 这样Ui::MainWindow 对象
ui 就可以直接访问setUi 函数及直接使用其中的对象指针.
ui 对象是没有父类的, 所以new 出来的ui,需要用delete 来删除. 见MainWindow 的析构.
MainWindow 类, 和Ui::MainWindow 类是两个完全不同的类, 前面是一个继承于QMainWindow 的子类. 而后者
是一个由mainwindow.ui 生成的控件布局的类. 它们的名字都叫MainWindow 而有点容易混淆, 其实它们都可以
不叫MainWindow 而叫别的名字.
关键点就这么多了. 再补充一下main.cpp 吧, 这很简单. qt 框架.
$ cat main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
概括一下: ui 就是一个由若干组件构成一个独立的类,用以完成布局,它没有父类. setupUi传来的指针是各个控件的父对象. 所以 ui被new 出来,还是需要delete 来删除的.