基礎篇
第一章 QT 基礎認知
1.1 什么是 QT(What)?
- 定義:跨平臺 C++ 應用開發框架,不僅用于 UI 設計,還包含核心功能(如事件、網絡、數據庫)。?
- 核心特性:?
- 跨平臺:一套代碼支持 Windows/macOS/Linux/ 嵌入式(如 ARM)/ 移動(iOS/Android);?
- 面向對象:基于 QObject 對象模型;?
- 豐富組件:內置數百個 UI 與功能組件;?
- 高效開發:Qt Creator IDE 可視化設計 + 代碼聯動。
1.2 為什么用 QT(Why)?
?
優勢? | 嵌入式開發場景價值? |
跨平臺? | 避免為不同嵌入式設備重復開發? |
低內存占用? | 適配嵌入式設備有限資源? |
支持硬件交互? | 可直接操作串口、GPIO 等嵌入式硬件? |
成熟社區與文檔? | 問題易檢索,降低學習成本? |
?
1.3 誰用 QT(Who)?
嵌入式開發工程師(工業屏 / 智能設備 UI)、桌面應用開發者、移動應用開發者。?
1.4 什么時候用 QT(When)?
- 需跨平臺開發時;?
- 需快速實現復雜 UI(如菜單欄、表格、對話框)時;?
- 嵌入式設備需可視化交互界面時。?
1.5 在哪用 QT(Where)?
- 嵌入式領域:工業控制屏(如 PLC 人機界面)、智能家電(如冰箱觸控屏);?
- 桌面領域:Windows/macOS 工具軟件(如串口助手);?
- 其他:醫療設備界面、車載系統 UI。?
1.6 怎么用 QT(How)?
核心流程:搭建環境→設計UI→編寫邏輯(信號與槽)→編譯調試→部署到目標設備。?
1.7 學習成本(How Much)?
- 技術前提:需掌握 C++ 基礎(類、指針、繼承);?
- 工具成本:Qt Creator+Qt SDK 免費(開源版本),商業授權需付費(嵌入式項目常用開源版);?
- 學習周期:2-4 周可掌握基礎開發。?
習題 1:QT 基礎認知判斷?
- 下列關于 QT 的描述正確的是( )?
A. QT 僅用于開發 Windows 桌面應用?
B. QT 基于 C++,支持跨平臺開發?
C. 嵌入式設備無法使用 QT?
D. QT 的核心功能僅包含 UI 設計?
解析 1?
- 答案:B?
- 分析:A 錯(QT 跨平臺,支持嵌入式 / 移動);C 錯(QT 是嵌入式 UI 開發常用框架);D 錯(QT 還包含網絡、數據庫等核心功能)。
第二章 QT 開發環境搭建
建議觀看B站迅為電子的視頻教程。
第三章 QT 核心概念(層級結構:概念→子知識點)?
3.1 核心模塊(QT 功能分類)?
模塊名? | 功能描述? | 嵌入式常用場景? |
Qt Core? | 核心功能(對象樹、事件、定時器)? | 內存管理、硬件定時器控制? |
Qt Widgets? | 桌面 / 嵌入式 UI 組件(窗口、按鈕)? | 開發工業屏交互界面? |
Qt GUI? | 圖形渲染(繪圖、字體、顏色)? | 繪制自定義控件(如儀表盤)? |
Qt Network? | 網絡通信(TCP/UDP/HTTP)? | 嵌入式設備聯網傳輸數據? |
Qt Sql? | 數據庫操作(SQLite/MySQL)? | 存儲設備運行日志? |
?
3.2 QObject 對象模型(QT 所有對象的基類)
核心作用:?
- 支持信號與槽(對象間通信);?
- 對象樹管理(自動回收內存);?
- 事件處理(如鼠標點擊、鍵盤輸入)。?
對象樹機制:?
- 創建 QObject 子類對象時,可指定 “父對象”(通過構造函數參數);?
- 父對象銷毀時,會自動銷毀所有子對象(避免內存泄漏);?
- 示例:QPushButton *btn = new QPushButton(this);(this為父對象,窗口銷毀時 btn 自動銷毀)。
3.3 元對象系統(MOC)?
作用:處理 QT 特有的語法(如 Q_OBJECT 宏、信號與槽),將其轉換為標準 C++ 代碼;?
關鍵組件:?
- Q_OBJECT 宏:需在 QObject 子類中聲明,否則 MOC 無法生成信號與槽代碼;?
- 元對象編譯器(MOC):Qt Creator 自動調用,生成moc_xxx.cpp文件。
習題 3:QObject 對象樹實操?
編寫代碼創建 3 個 QObject 子類對象(A、B、C),指定 A 為 B 的父對象,B 為 C 的父對象,在析構函數中打印 “對象 X 銷毀”,觀察 delete A 后的輸出順序,說明原因。
解析 3
#include <QObject>
#include <QDebug>
#include <QCoreApplication>class MyObject : public QObject {Q_OBJECT
public:~MyObject() {qDebug() << "對象" << objectName() << "銷毀";}
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);MyObject *A = new MyObject;A->setObjectName("A");MyObject *B = new MyObject(A); // A為B的父對象B->setObjectName("B");MyObject *C = new MyObject(B); // B為C的父對象C->setObjectName("C");delete A; // 銷毀父對象Areturn a.exec();
}
- 輸出順序:對象A銷毀 → 對象B銷毀 → 對象C銷毀(或 C→B→A,取決于對象樹遍歷順序);?
- 原因:QObject 對象樹機制,父對象銷毀時會遍歷所有子對象并銷毀,避免內存泄漏。
第四章 QT 基礎 UI 組件(模塊結構:按組件類型拆解)?
4.1 窗口組件(UI 容器)?
組件名? | 特點? | 用途? |
QMainWindow? | 含菜單欄、工具欄、狀態欄? | 主應用窗口(如文本編輯器)? |
QWidget? | 基礎空白窗口? | 自定義控件容器? |
QDialog? | 彈窗窗口(模態 / 非模態)? | 彈出 “確認”“設置” 對話框? |
?
示例:創建 QMainWindow 窗口(附字符模擬界面)
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[]) {QApplication a(argc, argv);QMainWindow w; w.setWindowTitle("嵌入式UI示例"); w.resize(800, 600); w.show(); return a.exec();
}
字符模擬界面:
+--------------------------------------------------------------+
| 文件 編輯 視圖 幫助 | 菜單欄(高25像素,默認灰色背景)
+--------------------------------------------------------------+
| 嵌入式UI示例 [最小化] [最大化] [關閉] | 標題欄(高30像素)
+--------------------------------------------------------------+
| |
| |
| | 中心空白區域(800×545像素)
| |
| |
+--------------------------------------------------------------+
| 狀態欄(默認隱藏,需手動啟用) | 狀態欄(高20像素)
+--------------------------------------------------------------+
界面說明:?
- QMainWindow 默認包含菜單欄和標題欄,狀態欄需通過statusBar()->show()手動啟用;?
- 中心區域為空白,需通過setCentralWidget設置組件容器后才能添加 UI 元素。
4.2 交互組件(用戶操作)?
組件名? | 功能? | 示例代碼? |
QPushButton? | 按鈕(點擊觸發事件)? | QPushButton *btn = new QPushButton("點擊我", &w);? |
QLineEdit? | 單行輸入框? | QLineEdit *edit = new QLineEdit("請輸入內容", &w);? |
QLabel? | 顯示文本 / 圖片? | QLabel *label = new QLabel("歡迎使用QT", &w);? |
?
4.3 布局管理(組件排版)?
問題:直接用setGeometry(x,y,w,h)固定組件位置,窗口縮放時組件會錯位;?
解決方案:使用布局管理器自動排版,常用布局:?
- QVBoxLayout:垂直布局(組件上下排列);?
- QHBoxLayout:水平布局(組件左右排列);?
- QGridLayout:網格布局(組件按行列排列)。
示例:垂直布局(QVBoxLayout)(附字符模擬界面)
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {QApplication a(argc, argv);QWidget w;w.setWindowTitle("布局示例");// 創建組件QPushButton *btn1 = new QPushButton("按鈕1");QPushButton *btn2 = new QPushButton("按鈕2");QLineEdit *edit = new QLineEdit("請輸入內容");// 創建垂直布局QVBoxLayout *layout = new QVBoxLayout(&w);layout->addWidget(edit); // 添加輸入框layout->addWidget(btn1); // 添加按鈕1layout->addWidget(btn2); // 添加按鈕2w.show();return a.exec();
}
字符模擬界面:
+----------------------------------------+
| 布局示例 [_] [□] [×] | 標題欄(寬300像素,高30像素)
+----------------------------------------+
| |
| [請輸入內容] | QLineEdit(高30像素,左右距10像素,灰色提示文本)
| |
| [ 按鈕1 ] | QPushButton(高35像素,寬280像素,文本居中)
| |
| [ 按鈕2 ] | QPushButton(與按鈕1同尺寸,間距15像素)
| |
+----------------------------------------+
界面說明:?
- 窗口總尺寸約 300×200 像素,組件垂直居中排列,上下組件間距 15 像素;?
- 拖動窗口邊緣縮放時,輸入框和按鈕會同步拉伸 / 收縮(寬度隨窗口變化,高度不變),保持布局整齊。
習題 4:UI 組件與布局實操?
- 創建一個 QMainWindow 窗口,要求:?
- 菜單欄添加 “控制” 菜單,包含 “開燈”“關燈” 兩個動作;?
- 中心部件用 QVBoxLayout,包含 1 個 QLabel(顯示 “燈狀態:關閉”)和 1 個 QPushButton(文本 “切換燈狀態”);?
- 窗口大小固定為 400x300。?
解析 4
代碼示例:
#include <QApplication>
#include <QMainWindow>
#include <QMenu>
#include <QAction>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>int main(int argc, char *argv[]) {QApplication a(argc, argv);QMainWindow w;w.setWindowTitle("燈控UI");w.setFixedSize(400, 300); // 固定窗口大小// 1. 菜單欄QMenu *controlMenu = w.menuBar()->addMenu("控制");QAction *lightOn = controlMenu->addAction("開燈");QAction *lightOff = controlMenu->addAction("關燈");// 2. 中心部件(QWidget+QVBoxLayout)QWidget *centralWidget = new QWidget(&w);w.setCentralWidget(centralWidget);QVBoxLayout *layout = new QVBoxLayout(centralWidget);// 3. 添加組件QLabel *statusLabel = new QLabel("燈狀態:關閉");QPushButton *toggleBtn = new QPushButton("切換燈狀態");layout->addWidget(statusLabel);layout->addWidget(toggleBtn);w.show();return a.exec();
}
字符模擬界面:
+----------------------------------------+
| 文件 編輯 控制 幫助 | 菜單欄(高25像素,“控制”菜單可點擊下拉)
+----------------------------------------+
| 燈控UI [_] [□] [×] | 標題欄(高30像素,窗口固定大小不可縮放)
+----------------------------------------+
| |
| 燈狀態:關閉 | QLabel(文本黑色,14號字體,居中)
| |
| | 垂直間距30像素
| [ 切換燈狀態 ] | QPushButton(寬120像素,高35像素,文本居中)
| |
| |
+----------------------------------------+
界面說明:?
- 點擊菜單欄 “控制”,下拉顯示 “開燈”“關燈” 選項(黑色文本,hover 時背景變為淺灰色);?
- 中心區域標簽和按鈕垂直居中,窗口背景為白色,組件無額外樣式(默認系統風格)。
第五章 QT 信號與槽
5.1 核心原理(對象間通信機制)?
- 信號(Signal):對象狀態變化時發出的 “通知”(如按鈕點擊clicked()、文本變化textChanged());?
- 槽(Slot):接收信號并執行的函數(如窗口關閉close()、更新文本setText());?
- 連接(Connect):通過connect函數將 “信號” 與 “槽” 綁定,信號觸發時自動執行槽函數。
5.2 語法規則(推薦 Qt 5 + 新語法)
connect(發送者對象, &發送者類::信號名, 接收者對象, &接收者類::槽函數名);
參數說明:?
- 發送者:發出信號的對象(如 QPushButton);?
- 信號:發送者的信號(如&QPushButton::clicked);?
- 接收者:執行槽函數的對象(如 QLabel);?
- 槽函數:接收者的函數(如&QLabel::setText)。
5.3 常用信號與槽示例?
發送者組件? | 信號名? | 接收者組件? | 槽函數名? | 功能描述? |
QPushButton? | clicked()? | QMainWindow? | close()? | 點擊按鈕關閉窗口? |
QLineEdit? | textChanged(QString)? | QLabel? | setText(QString)? | 輸入框文本變化時更新標簽? |
QAction? | triggered()? | QWidget? | show()? | 點擊菜單動作顯示窗口? |
?
5.4 自定義信號與槽?
步驟:?
- 新建 QObject 子類,添加Q_OBJECT宏;?
- 用signals:關鍵字聲明信號(僅聲明,無實現);?
- 用public slots:聲明槽函數(需實現);?
- 用emit關鍵字發送信號。
習題 5:信號與槽實操?
基于習題 4 的燈控 UI,補充信號與槽邏輯:?
- 點擊 “切換燈狀態” 按鈕,觸發toggleLight槽函數,更新 QLabel 顯示狀態;?
- 點擊菜單欄 “開燈”,直接設置燈為開啟狀態;點擊 “關燈”,直接設置為關閉狀態。?
解析 5?
完整代碼:
#include <QApplication>
#include <QMainWindow>
#include <QMenu>
#include <QAction>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QObject>class LightControl : public QObject {Q_OBJECT
public:LightControl(QLabel *label) : m_label(label) {}
signals:void lightStatusChanged(QString status);
public slots:void toggleLight() {m_isOn = !m_isOn;emit lightStatusChanged("燈狀態:" + (m_isOn ? "開啟" : "關閉"));}void turnOnLight() { // 開燈槽函數m_isOn = true;emit lightStatusChanged("燈狀態:開啟");}void turnOffLight() { // 關燈槽函數m_isOn = false;emit lightStatusChanged("燈狀態:關閉");}
private:bool m_isOn = false;QLabel *m_label;
};int main(int argc, char *argv[]) {QApplication a(argc, argv);QMainWindow w;w.setWindowTitle("燈控UI");w.setFixedSize(400, 300);// 1. 菜單欄QMenu *controlMenu = w.menuBar()->addMenu("控制");QAction *lightOn = controlMenu->addAction("開燈");QAction *lightOff = controlMenu->addAction("關燈");// 2. 中心部件QWidget *centralWidget = new QWidget(&w);w.setCentralWidget(centralWidget);QVBoxLayout *layout = new QVBoxLayout(centralWidget);QLabel *statusLabel = new QLabel("燈狀態:關閉");QPushButton *toggleBtn = new QPushButton("切換燈狀態");layout->addWidget(statusLabel);layout->addWidget(toggleBtn);// 3. 信號與槽連接LightControl *lightCtrl = new LightControl(statusLabel);QObject::connect(toggleBtn, &QPushButton::clicked, lightCtrl, &LightControl::toggleLight);QObject::connect(lightOn, &QAction::triggered, lightCtrl, &LightControl::turnOnLight);QObject::connect(lightOff, &QAction::triggered, lightCtrl, &LightControl::turnOffLight);QObject::connect(lightCtrl, &LightControl::lightStatusChanged, statusLabel, &QLabel::setText);w.show();return a.exec();
}
#include "main.moc"
字符模擬交互界面:?
1. 初始狀態
+----------------------------------------+
| 文件 編輯 控制 幫助 |
+----------------------------------------+
| 燈控UI [_] [□] [×] |
+----------------------------------------+
| |
| 燈狀態:關閉 | 初始標簽文本
| |
| [ 切換燈狀態 ] | 按鈕默認樣式
| |
+----------------------------------------+
2. 點擊 “切換燈狀態” 按鈕后
+----------------------------------------+
| 文件 編輯 控制 幫助 |
+----------------------------------------+
| 燈控UI [_] [□] [×] |
+----------------------------------------+
| |
| 燈狀態:開啟 | 標簽文本實時更新
| |
| [ 切換燈狀態 ] | 按鈕樣式不變
| |
+----------------------------------------+
3. 點擊 “控制→開燈” 后
+----------------------------------------+
| 文件 編輯 控制▼ 幫助 | “控制”菜單下拉
| 開燈 | 選中“開燈”選項(背景淺灰)
| 關燈 |
+----------------------------------------+
| 燈控UI [_] [□] [×] |
+----------------------------------------+
| |
| 燈狀態:開啟 | 標簽直接更新為“開啟”
| |
| [ 切換燈狀態 ] |
| |
+----------------------------------------+
交互說明:?
- 所有操作無延遲,標簽文本實時更新;?
- 點擊 “控制→關燈” 時,標簽會立即變為 “燈狀態:關閉”,邏輯與 “開燈” 相反。
第六章 QT 事件處理(層級結構:事件類型→處理方式)
6.1 什么是 QT 事件?
定義:系統或用戶觸發的行為(如鼠標點擊、鍵盤輸入、窗口縮放),QT 通過 “事件隊列” 管理事件。?
常用事件類型:?
- QMouseEvent:鼠標事件(點擊、移動、滾輪);?
- QKeyEvent:鍵盤事件(按鍵按下、松開);?
- QResizeEvent:窗口大小變化事件。
6.2 事件處理方式(重點:重寫事件函數)?
- 核心方法:重寫 QWidget 的虛函數(如mousePressEvent、keyPressEvent),實現自定義邏輯。?
- 規則:重寫后需調用父類事件函數(如QWidget::mousePressEvent(event)),否則會屏蔽默認行為(如窗口無法拖動)。
示例:鼠標點擊顯示坐標(附字符模擬界面)
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>
#include <QMouseEvent>class MouseWidget : public QWidget {Q_OBJECT
public:MouseWidget(QWidget *parent = nullptr) : QWidget(parent) {QVBoxLayout *layout = new QVBoxLayout(this);m_label = new QLabel("點擊窗口查看鼠標坐標");layout->addWidget(m_label);}
protected:// 重寫鼠標按下事件void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) { // 僅處理左鍵點擊QString coord = QString("鼠標左鍵坐標:(%1, %2)").arg(event->x()).arg(event->y());m_label->setText(coord);}QWidget::mousePressEvent(event); // 保留父類默認行為}
private:QLabel *m_label;
};int main(int argc, char *argv[]) {QApplication a(argc, argv);MouseWidget w;w.setWindowTitle("鼠標事件示例");w.resize(400, 300);w.show();return a.exec();
}
#include "main.moc"
字符模擬界面:?
1. 初始狀態
+----------------------------------------+
| 鼠標事件示例 [_] [□] [×] | 標題欄(寬400像素)
+----------------------------------------+
| |
| 點擊窗口查看鼠標坐標 | QLabel(文本居中,14號字體)
| |
| |
| |
+----------------------------------------+
2. 鼠標左鍵點擊窗口中心后
+----------------------------------------+
| 鼠標事件示例 [_] [□] [×] |
+----------------------------------------+
| |
| 鼠標左鍵坐標:(200, 150) | 標簽文本更新為坐標(中心位置X=200,Y=150)
| |
| |
| |
+----------------------------------------+
界面說明:?
- 點擊窗口左上角(靠近邊緣),標簽顯示 “鼠標左鍵坐標:(5, 5)”;?
- 右鍵點擊窗口無任何變化,拖動標題欄移動窗口時,坐標文本保持不變。
習題 6:事件處理實操?
基于上述示例,補充鍵盤事件處理:?
- 按下 “Ctrl+S” 鍵,在 QLabel 上顯示 “快捷鍵 Ctrl+S 按下”;?
- 按下 “ESC” 鍵,關閉窗口。
解析 6?
- 補充代碼(MouseWidget 類中):
protected:// 新增:重寫鍵盤按下事件void keyPressEvent(QKeyEvent *event) override {// 判斷Ctrl+S(event->modifiers()獲取組合鍵)if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_S) {m_label->setText("快捷鍵Ctrl+S按下");}// 判斷ESC鍵else if (event->key() == Qt::Key_Escape) {close(); // 關閉窗口}QWidget::keyPressEvent(event); // 調用父類}
字符模擬交互效果:?
1. 按下 “Ctrl+S” 后
+----------------------------------------+
| 鼠標事件示例 [_] [□] [×] |
+----------------------------------------+
| |
| 快捷鍵Ctrl+S按下 | 標簽文本替換為快捷鍵提示
| |
| |
| |
+----------------------------------------+
2. 按下 “ESC” 后?
- 窗口直接關閉,程序退出,無任何彈窗提示;?
- 若當前標簽顯示坐標或快捷鍵文本,按下 “ESC” 后直接退出,不保留狀態。?
交互說明:?
- 僅當窗口處于激活狀態(標題欄為藍色,Windows 系統)時,鍵盤事件才會被觸發;?
- 按下其他鍵(如 “A”“1”“空格”),標簽無變化,保持當前文本。
QT開發知識點梳理
后續更新