文章目录
⭐前言
本文将带大家,查看一个默认的Qt Widget程序可能会涉及哪些方面的内容。
本文默认使用IDE为Qt Creator和qmake编译套件。
当然由于个人能力和水平的局限性,并不可能带领大家看到所有的全貌。
⭐创建
🛠️选择一个模板
选择 Application (Qt)
并选择一个窗口应用Qt Widgets Application
。
🛠️Location
选择一个项目生成的位置,注意,不要出现中文路径。
这里的名称默认是untitled
,大家可以改成自己项目的名称。也不要有中文。
🛠️构建系统
选择qmake,当然目前Qt6在大力推行cmake进行编译。
本文这里以传统的qmake为例。
而最后的Qbs是qt提出的另一种构建方式
但是在2018年宣布正式弃用:Deprecation of Qbs (qt.io)
🛠️Details
这里是生成默认代码的配置。
默认情况下,头文件,源文件,ui文件三者会跟随类名。这里默认使用的是QMainWindow
。
继承关系链 QMainWindow -> QWidget -> QObject
。
🛠️Translation
翻译文件,国际化翻译配置,一般都是根据需要生成。这里默认无即可。
🛠️构建套件(Kit)
这里Qt Creator会根据安装时的qt版本显示。这里随意选择即可,后面还可以自己再选择。
🛠️汇总
项目管理,这里没有子项目。因此直接默认。
一般这些东西都是在项目过程中手动管理进去的。
⭐项目
⚒️概要
构建目录
这里的构建目录会默认生成在.pro
文件所在文件夹的同级中。
里面包含了,qt版本
,编译器
,debug-release
等等信息。
C:\Users\lotus\Desktop\build-untitled-Desktop_Qt_5_15_2_MinGW_32_bit-Debug
⚒️构建步骤
在构建目录中,分别执行qmake指令和make指令,即可编译好我们的Qt程序。
当然下面并非是真正的执行指令,而是一些显示的配置参数。
qmake
D:/Qt/5.15.2/mingw81_32/bin/qmake.exe C:\Users\lotus\Desktop\untitled\untitled.pro -spec win32-g++ "CONFIG+=debug" "CONFIG+=qml_debug" && D:/Qt/Tools/mingw810_32/bin/mingw32-make.exe qmake_all
Make
mingw32-make.exe -j16 in C:\Users\lotus\Desktop\build-untitled-Desktop_Qt_5_15_2_MinGW_32_bit-Debug
⚒️清除步骤
删除一些中间文件,比如.o
,moc_
等等文件,其中文件夹不删除。
mingw32-make.exe clean -j16 in C:\Users\lotus\Desktop\build-untitled-Desktop_Qt_5_15_2_MinGW_32_bit-Debug
⭐Code
🔦untitled.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
QT
Qt的核心库,如core
,gui
,widgets
等等
CONFIG
添加相关配置,比如这里希望以c++17的标准编译。
DEFINES
添加宏定义,此处的QT_DISABLE_DEPRECATED_BEFORE=0x060000
。表示如果使用废弃的接口函数,则将无法编译。
如果不指定值,则默认值为1。
SOURCES
原文件
HEADERS
头文件
FORMS
ui文件
分支判断
qnx:
表示在qnx的环境下。
else:
类似if-else
当然这里也可以添加{}
块作用域。
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
🔦main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
QApplication
是整个程序的核心,管理了qt的所有主事件循环,用exec()
进入阻塞等待。
当退出时,返回一个int。
w.show()
这里建立一个ui组件,并显示。
当最后一个ui关闭时,则退出主时间循环,即exec()
结束,并返回。
🔦mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
元对象
继承自QObject
,并包含宏Q_OBJECT
。
继承关系:QMainWindow -> QWidget -> QObject
将该文件通过moc解析。
moc.exe mainwindow.h -o mainwindow.moc.cpp
mainwindow.moc.cpp
/****************************************************************************
** Meta object code from reading C++ file 'mainwindow.h'
**
** Created by: The Qt Meta Object Compiler version 68 (Qt 6.2.4)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include <memory>
#include "mainwindow.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'mainwindow.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 68
#error "This file was generated using the moc from 6.2.4. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
struct qt_meta_stringdata_MainWindow_t {
const uint offsetsAndSize[2];
char stringdata0[11];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(offsetof(qt_meta_stringdata_MainWindow_t, stringdata0) + ofs), len
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 10) // "MainWindow"
},
"MainWindow"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_MainWindow[] = {
// content:
10, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
0 // eod
};
void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
(void)_o;
(void)_id;
(void)_c;
(void)_a;
}
const QMetaObject MainWindow::staticMetaObject = { {
QMetaObject::SuperData::link<QMainWindow::staticMetaObject>(),
qt_meta_stringdata_MainWindow.offsetsAndSize,
qt_meta_data_MainWindow,
qt_static_metacall,
nullptr,
qt_incomplete_metaTypeArray<qt_meta_stringdata_MainWindow_t
, QtPrivate::TypeAndForceComplete<MainWindow, std::true_type>
>,
nullptr
} };
const QMetaObject *MainWindow::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *MainWindow::qt_metacast(const char *_clname)
{
if (!_clname) return nullptr;
if (!strcmp(_clname, qt_meta_stringdata_MainWindow.stringdata0))
return static_cast<void*>(this);
return QMainWindow::qt_metacast(_clname);
}
int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QMainWindow::qt_metacall(_c, _id, _a);
return _id;
}
QT_WARNING_POP
QT_END_MOC_NAMESPACE
namespace Ui { class MainWindow; }
是ui文件中,顶层对象名称就是这里的类名。可以通过解析ui文件进行查看。
当然这里是一个典型的Pimpl
技巧。
🔦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;
}
该文件核心是查看这两个头文件。
#include "mainwindow.h"
#include "ui_mainwindow.h"
<ui_mainwindow.h>
是通过ui文件生成的C++代码。(将xml转化为cpp代码)
🔦mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar"/>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
xml
显然易见的,ui文件的本质是一个xml文件。
uic
可以通过uic指令将ui文件转化为cpp代码。
uic mainwindow.ui -o ui_mainwindow.h
ui_mainwindow.h
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 6.2.4
**
** 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
END
⭐视频讲解
视频讲解参见
关注我,学习更多C/C++,算法,计算机知识
B站:
👨💻主页:天赐细莲 bilibili