当创建完项目时看到这样的界面:
本文将聚焦与项目创建后的这5个文件的解析,这5个文件分别为: test250225
, mywidget.h
, main.cpp
, mywidget.cpp
, mywidget.ui
。
现在开始逐个解析
main.cpp
内容解析#include "mywidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyWidget w;
w.show();
return a.exec();
}
该函数中的QApplication a
这是编写Qt图形化界面一定需要的对象,它的作用为:
QApplication
对象,否则 GUI 组件无法正常工作。继续往下看,MyWidget
是创建项目时,填写的类名。
w.show()
的作用是创建一个控件对象,并显示出来,同时你还可以用.hide()
让控件隐藏,注意Wight
的父类是QWight
,Wight
中的方法大部分都是继承至父类。
然后我们来看a.exec()
这个有没有很熟悉,如果你学过Linux,在Linux中有一个进程程序替换的函数,确切来说是6个函数,他们是一个系列,可以把可执行文件中的代码和数据替换到当前进程中。
是不是觉得他们有什么关系呢?
完全没有如何关系!!!
只是名字一样而已,就像家豪这个名字,可能你遇到过几个家豪,只是名字一样而已。
在计算机的世界,这种情况并不少见,你还能想到其他例子吗?
你肯定想到了计算机中的栈和堆了吧,有数据结构中的栈和堆,还有操作系统中的栈和堆甚至还有JVM中的栈和堆,这3种栈和堆都有不同的概念,但是他们的名字相同。
主函数介绍完了,我们开始介绍其他文件。
mywidget.h
内容解析#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACE
class MyWidget : public QWidget//继承父类
{
Q_OBJECT//宏替换
public:
MyWidget(QWidget *parent = nullptr);
~MyWidget();
private:
Ui::MyWidget *ui;
};
#endif // MYWIDGET_H
先看这段代码:
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACE
其中QT_BEGIN_NAMESPACE和QT_END_NAMESPACE
是Qt提供的命名空间宏。
namespace Ui { class MyWidget; }
是一种向前声明,用于声明UI::MyWidget
这个类。
在这里我们主要还是关注这个类,这个类就是我们创建项目时所命名的,可以看到它确实继承至QWight
我们可以看到类中存在着一个宏,Q_OBJECT
是Qt中一个内置的宏,宏本质上就是文本替换,其实它会替换为一大堆代码。
跳转过去看看:
看不懂。。。
Qt中有一个非常核心的机制,“信号和槽”,如果某个类想要使用"信号和槽"就需要引入这个宏。
在往下看,就是构造函数和析构函数,析构函数没什么好讲的,我们看到构造函数,构造函数的形参是一个QWidget
类型的缺省。
这里其实存在着一个Qt中引入的对象树机制(目前不解释)。
创建的Qt对象可把这个对象给挂到对象树上,往树上挂的时候就需要指定父节点(这里的树是n叉树)
mywidget.cpp
内容解析#include "mywidget.h"//创建项目生成的头文件
#include "ui_mywidget.h"//form file被qmake生成的头文件
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MyWidget)
{
ui->setupUi(this);//把form file生成的界面和当前widget关联起来
}
MyWidget::~MyWidget()
{
delete ui;
}
form file
内容解析双击文件mywidget.ui
文件
会进入设计界面
左边是Qt内置的1控件,可以直接拖拽到右边的程序窗口,没错我们还可以这样创建出具体的界面。每个控件都有很多属性,我们可以自行设计控件的属性
点击左侧栏的编辑按钮,此时显示的内容,就是.ui文的本体了
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MyWidget</class>
<widget class="QWidget" name="MyWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MyWidget</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
看到这个格式有没有一点熟悉,有点像html
的标签模式,但是呢这个格式被称为xml
格式
xml这里的标签是可以程序员自定义的,有点类似于网络中的自定义应用层协议。而html的标签是由标准委员会约定的,所有的浏览器也是按照约定来解释的
Qt中使用xml文件就是描述程序的界面是啥样的,再进一步的qmake文件会调用相关的工具依据这个xml文件生成一些C++代码,从而把完整的界面构造出来。
.pro
内容解析QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mywidget.cpp
HEADERS += \
mywidget.h
FORMS += \
mywidget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
现在看到.pro
Qt的工程文件,也是qmake
工具构建的重要依据,注意:.pro
类似Linux中的makefile
文件是一个自动化构建工具
直接看总结版:
部分 | 作用 |
---|---|
QT += core gui | 添加 QtCore 和 QtGui 模块(基础功能和 GUI 支持)。 |
QT += widgets | Qt 5+ 需要额外添加 QtWidgets 以使用 QWidget。 |
CONFIG += c++11 | 启用 C++11 语法支持。 |
DEFINES += QT_DEPRECATED_WARNINGS | 启用 Qt 过时 API 的警告。 |
SOURCES += main.cpp mywidget.cpp | 指定 .cpp 源文件。 |
HEADERS += mywidget.h | 指定 .h 头文件。 |
FORMS += mywidget.ui | 指定 Qt Designer 的 .ui 文件。 |
target.path | 设置不同平台的安装路径。 |
红框中的内容是描述当前项目中,参与构建的文件都有什么,这地方不需要手动修改,qt Creator会帮我们自动维护好。 上面我们看到的都是源代码,其实在编译运行中还会产生一些中间文件。
打开文件自愿管理器,看看项目对应的目录是什么样子~
在运行一次程序后,就会在项目并列的地方多出来一个buildxxx目录 这个目录是用来存储运行过程中的临时文件的。
打开目录,看到了一个makefile文件,看来编译Qt程序还是会用到makefile文件啊,由qmake自动生成。
然后我们,再看到ui_mywidget.h
文件,该文件是根据前面的xml
文件自动生成的,打开ui_mywidget.h
文件:
/********************************************************************************
** Form generated from reading UI file 'mywidget.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_MYWIDGET_H
#define UI_MYWIDGET_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MyWidget
{
public:
void setupUi(QWidget *MyWidget)
{
if (MyWidget->objectName().isEmpty())
MyWidget->setObjectName(QString::fromUtf8("MyWidget"));
MyWidget->resize(800, 600);
retranslateUi(MyWidget);
QMetaObject::connectSlotsByName(MyWidget);
} // setupUi
void retranslateUi(QWidget *MyWidget)
{
MyWidget->setWindowTitle(QCoreApplication::translate("MyWidget", "MyWidget", nullptr));
} // retranslateUi
};
namespace Ui {
class MyWidget: public Ui_MyWidget {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MYWIDGET_H
总结来说,Qt 初始代码的结构清晰且模块化,充分体现了 Qt 框架的设计哲学。从 QApplication 的初始化到 QWidget 的父子管理机制,再到 .pro 文件的配置,每个部分都在确保应用的稳定性和可扩展性。理解这些基础代码,不仅有助于掌握 Qt 的事件循环、窗口管理和资源组织方式,还能为后续的开发打下坚实的基础。希望这篇解析能帮助你更高效地入门 Qt,并为更复杂的应用开发做好准备。