Qt 窗口类和对应ui之间的关系
我们知道,在Qt中每一个窗口类都应对应一个可编辑的可视化界面(*.ui)。那么,它们之间是如何依赖或者联系起来的呢?
先看源码
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget // 继承自QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui; // 定义Ui中的Widget为私有变量
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h" // 引入ui_widget.h头文件,方便后面把ui和当前窗口类合二为一
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);// 调用ui_widget.h中的方法,它包括了widget.h中引入的命名空间的Widget的定义
}
Widget::~Widget()
{
delete ui;
}
ui_widget.h
/********************************************************************************
** Form generated from reading UI file 'widget.ui'
**
** Created by: Qt User Interface Compiler version 5.14.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_WIDGET_H
#define UI_WIDGET_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Widget
{
public:
void setupUi(QWidget *Widget) // 聚合了基类QWidget,并把它当作一个局部变量
{
if (Widget->objectName().isEmpty())
Widget->setObjectName(QString::fromUtf8("Widget"));
Widget->resize(800, 600);
retranslateUi(Widget);
QMetaObject::connectSlotsByName(Widget);
} // setupUi
void retranslateUi(QWidget *Widget)
{
Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", nullptr));
} // retranslateUi
};
namespace Ui { // 命名空间的详细定义,并继承自当前类
class Widget: public Ui_Widget {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_WIDGET_H
QWidget.h
// ...
class QWidget{
#ifdef Q_QDOC
void setupUi(QWidget *widget); // widget.cpp中使用的setupUi应该不是这个,而是ui_widget.h中定义的那个
// ...
}
图解
图解就是:
模拟实现
根据代码,以及图解关系,我们可以自定义实现这个关系的过程。
定义一个基类QWidget
。
QWidget.h
// QWidget.h
class QWidget{
// 模拟的时候用不到
//public:
// void setupUi(QWidget *widget);
};
定义一个中间类ui_widget
,把窗口和ui合二为一。
ui_widget.h
// ui_widget.h
class Ui_Widget {
public:
void setupUi(QWidget *widget) {
//合二为一的方法
}
};
// 定义命名空间
namespace Ui {
class Widget : public Ui_Widget {};
}
接下来定义一个窗口类。
widget.h
// Widget.h
#include "QWidget.h" // 继承需要引入头文件
namespace Ui{ // 声明命名空间,具体的定义在ui_widget.h中
class Widget;
}
class Widget: public QWidget {
public:
Widget();
private:
Ui::Widget *ui;
};
widget.cpp
// Widget.cpp
#include "Widget.h"
#include "ui_widget.h" // 需要使用到setuiUp方法,所以引入
Widget::Widget():ui(new Ui::Widget){
ui->setupUi(this);// 因为Widget继承了QWidget所以才能传递this
}