文章目錄
- ?前言
- ?創建
- 🛠?選擇一個模板
- 🛠?Location
- 🛠?構建系統
- 🛠?Details
- 🛠?Translation
- 🛠?構建套件(Kit)
- 🛠?匯總
- ?項目
- ??概要
- ??構建步驟
- ??清除步驟
- ?Code
- 🔦untitled.pro
- 🔦main.cpp
- 🔦mainwindow.h
- 🔦mainwindow.cpp
- 🔦mainwindow.ui
- END
- ?視頻講解
?前言
本文將帶大家,查看一個默認的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 guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += 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.0SOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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.)"
#endifQT_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_LITERALstatic const uint qt_meta_data_MainWindow[] = {// content:10, // revision0, // classname0, 0, // classinfo0, 0, // methods0, 0, // properties0, 0, // enums/sets0, 0, // constructors0, // flags0, // signalCount0 // 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_NAMESPACEclass 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);} // setupUivoid retranslateUi(QMainWindow *MainWindow){MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));} // retranslateUi};namespace Ui {class MainWindow: public Ui_MainWindow {};
} // namespace UiQT_END_NAMESPACE#endif // UI_MAINWINDOW_H
END
?視頻講解
視頻講解參見
![]()
關注我,學習更多C/C++,算法,計算機知識
B站:
👨?💻主頁:天賜細蓮 bilibili
![]()