QT零基础入门教程

基础篇

第一章 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 基础认知判断​

  1. 下列关于 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 所有对象的基类)

核心作用:​

  1. 支持信号与槽(对象间通信);
  2. 对象树管理(自动回收内存);
  3. 事件处理(如鼠标点击、键盘输入)。

对象树机制:​

  1. 创建 QObject 子类对象时,可指定 "父对象"(通过构造函数参数);
  2. 父对象销毁时,会自动销毁所有子对象(避免内存泄漏);
  3. 示例: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

cpp 复制代码
#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; // 销毁父对象A
    return a.exec();
}
  • 输出顺序:对象A销毁 → 对象B销毁 → 对象C销毁(或 C→B→A,取决于对象树遍历顺序);
  • 原因:QObject 对象树机制,父对象销毁时会遍历所有子对象并销毁,避免内存泄漏。

第四章 QT 基础 UI 组件(模块结构:按组件类型拆解)​

4.1 窗口组件(UI 容器)​

|--------------|-----------------|------------------|
| 组件名​ | 特点​ | 用途​ |
| QMainWindow​ | 含菜单栏、工具栏、状态栏​ | 主应用窗口(如文本编辑器)​ |
| QWidget​ | 基础空白窗口​ | 自定义控件容器​ |
| QDialog​ | 弹窗窗口(模态 / 非模态)​ | 弹出 "确认""设置" 对话框​ |

示例:创建 QMainWindow 窗口(附字符模拟界面)

cpp 复制代码
#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();
}

字符模拟界面:

cpp 复制代码
+--------------------------------------------------------------+
|  文件   编辑   视图   帮助                                   |  菜单栏(高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)(附字符模拟界面)

cpp 复制代码
#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); // 添加按钮1
    layout->addWidget(btn2); // 添加按钮2
    w.show();
    return a.exec();
}

字符模拟界面:

cpp 复制代码
+----------------------------------------+
|  布局示例                  [_] [□] [×]  |  标题栏(宽300像素,高30像素)
+----------------------------------------+
|                                        |
|  [请输入内容]                          |  QLineEdit(高30像素,左右距10像素,灰色提示文本)
|                                        |
|  [          按钮1          ]           |  QPushButton(高35像素,宽280像素,文本居中)
|                                        |
|  [          按钮2          ]           |  QPushButton(与按钮1同尺寸,间距15像素)
|                                        |
+----------------------------------------+

界面说明:​

  • 窗口总尺寸约 300×200 像素,组件垂直居中排列,上下组件间距 15 像素;
  • 拖动窗口边缘缩放时,输入框和按钮会同步拉伸 / 收缩(宽度随窗口变化,高度不变),保持布局整齐。

习题 4:UI 组件与布局实操​

  1. 创建一个 QMainWindow 窗口,要求:
  • 菜单栏添加 "控制" 菜单,包含 "开灯""关灯" 两个动作;
  • 中心部件用 QVBoxLayout,包含 1 个 QLabel(显示 "灯状态:关闭")和 1 个 QPushButton(文本 "切换灯状态");
  • 窗口大小固定为 400x300。

解析 4

代码示例:

cpp 复制代码
#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();
}

字符模拟界面:

cpp 复制代码
+----------------------------------------+
|  文件   编辑   控制   帮助             |  菜单栏(高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 + 新语法)

cpp 复制代码
connect(发送者对象, &发送者类::信号名, 接收者对象, &接收者类::槽函数名);

参数说明:​

  1. 发送者:发出信号的对象(如 QPushButton);
  2. 信号:发送者的信号(如&QPushButton::clicked);
  3. 接收者:执行槽函数的对象(如 QLabel);
  4. 槽函数:接收者的函数(如&QLabel::setText)。

5.3 常用信号与槽示例​

|--------------|-----------------------|--------------|-------------------|---------------|
| 发送者组件​ | 信号名​ | 接收者组件​ | 槽函数名​ | 功能描述​ |
| QPushButton​ | clicked()​ | QMainWindow​ | close()​ | 点击按钮关闭窗口​ |
| QLineEdit​ | textChanged(QString)​ | QLabel​ | setText(QString)​ | 输入框文本变化时更新标签​ |
| QAction​ | triggered()​ | QWidget​ | show()​ | 点击菜单动作显示窗口​ |

5.4 自定义信号与槽​

步骤:​

  1. 新建 QObject 子类,添加Q_OBJECT宏;
  2. 用signals:关键字声明信号(仅声明,无实现);
  3. 用public slots:声明槽函数(需实现);
  4. 用emit关键字发送信号。

习题 5:信号与槽实操​

基于习题 4 的灯控 UI,补充信号与槽逻辑:​

  • 点击 "切换灯状态" 按钮,触发toggleLight槽函数,更新 QLabel 显示状态;
  • 点击菜单栏 "开灯",直接设置灯为开启状态;点击 "关灯",直接设置为关闭状态。

解析 5​

完整代码:

cpp 复制代码
#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. 初始状态
cpp 复制代码
+----------------------------------------+
|  文件   编辑   控制   帮助             |
+----------------------------------------+
|  灯控UI                    [_] [□] [×]  |
+----------------------------------------+
|                                        |
|                灯状态:关闭             |  初始标签文本
|                                        |
|                [ 切换灯状态 ]          |  按钮默认样式
|                                        |
+----------------------------------------+
  1. 点击 "切换灯状态" 按钮后
cpp 复制代码
+----------------------------------------+
|  文件   编辑   控制   帮助             |
+----------------------------------------+
|  灯控UI                    [_] [□] [×]  |
+----------------------------------------+
|                                        |
|                灯状态:开启             |  标签文本实时更新
|                                        |
|                [ 切换灯状态 ]          |  按钮样式不变
|                                        |
+----------------------------------------+
  1. 点击 "控制→开灯" 后
cpp 复制代码
+----------------------------------------+
|  文件   编辑   控制▼  帮助             |  "控制"菜单下拉
|                  开灯                  |  选中"开灯"选项(背景浅灰)
|                  关灯                  |
+----------------------------------------+
|  灯控UI                    [_] [□] [×]  |
+----------------------------------------+
|                                        |
|                灯状态:开启             |  标签直接更新为"开启"
|                                        |
|                [ 切换灯状态 ]          |
|                                        |
+----------------------------------------+

交互说明:​

  • 所有操作无延迟,标签文本实时更新;
  • 点击 "控制→关灯" 时,标签会立即变为 "灯状态:关闭",逻辑与 "开灯" 相反。

第六章 QT 事件处理(层级结构:事件类型→处理方式)

6.1 什么是 QT 事件​

定义:系统或用户触发的行为(如鼠标点击、键盘输入、窗口缩放),QT 通过 "事件队列" 管理事件。​

常用事件类型:​

  1. QMouseEvent:鼠标事件(点击、移动、滚轮);
  2. QKeyEvent:键盘事件(按键按下、松开);
  3. QResizeEvent:窗口大小变化事件。

6.2 事件处理方式(重点:重写事件函数)​

  • 核心方法:重写 QWidget 的虚函数(如mousePressEvent、keyPressEvent),实现自定义逻辑。
  • 规则:重写后需调用父类事件函数(如QWidget::mousePressEvent(event)),否则会屏蔽默认行为(如窗口无法拖动)。

示例:鼠标点击显示坐标(附字符模拟界面)

cpp 复制代码
#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. 初始状态
cpp 复制代码
+----------------------------------------+
|  鼠标事件示例              [_] [□] [×]  |  标题栏(宽400像素)
+----------------------------------------+
|                                        |
|          点击窗口查看鼠标坐标           |  QLabel(文本居中,14号字体)
|                                        |
|                                        |
|                                        |
+----------------------------------------+
  1. 鼠标左键点击窗口中心后
cpp 复制代码
+----------------------------------------+
|  鼠标事件示例              [_] [□] [×]  |
+----------------------------------------+
|                                        |
|        鼠标左键坐标:(200, 150)        |  标签文本更新为坐标(中心位置X=200,Y=150)
|                                        |
|                                        |
|                                        |
+----------------------------------------+

界面说明:​

  • 点击窗口左上角(靠近边缘),标签显示 "鼠标左键坐标:(5, 5)";
  • 右键点击窗口无任何变化,拖动标题栏移动窗口时,坐标文本保持不变。

习题 6:事件处理实操​

基于上述示例,补充键盘事件处理:​

  • 按下 "Ctrl+S" 键,在 QLabel 上显示 "快捷键 Ctrl+S 按下";
  • 按下 "ESC" 键,关闭窗口。

解析 6​

  • 补充代码(MouseWidget 类中):
cpp 复制代码
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" 后
cpp 复制代码
+----------------------------------------+
|  鼠标事件示例              [_] [□] [×]  |
+----------------------------------------+
|                                        |
|        快捷键Ctrl+S按下                 |  标签文本替换为快捷键提示
|                                        |
|                                        |
|                                        |
+----------------------------------------+
  1. 按下 "ESC" 后​
  • 窗口直接关闭,程序退出,无任何弹窗提示;
  • 若当前标签显示坐标或快捷键文本,按下 "ESC" 后直接退出,不保留状态。

交互说明:​

  • 仅当窗口处于激活状态(标题栏为蓝色,Windows 系统)时,键盘事件才会被触发;
  • 按下其他键(如 "A""1""空格"),标签无变化,保持当前文本。

QT开发知识点梳理

后续更新

相关推荐
kyle~3 小时前
排序---插入排序(Insertion Sort)
c语言·数据结构·c++·算法·排序算法
奔跑吧邓邓子3 小时前
【C++实战⑦】C++函数实战:从基础到项目应用
c++·实战·函数
HMBBLOVEPDX3 小时前
C++(静态函数)
开发语言·c++
张晓~183399481214 小时前
短视频矩阵源码-视频剪辑+AI智能体开发接入技术分享
c语言·c++·人工智能·矩阵·c#·php·音视频
一枝小雨5 小时前
【C++】list 容器操作
开发语言·c++·笔记·list·学习笔记
HMBBLOVEPDX5 小时前
C++(继承和多态)
开发语言·c++·继承和多态
愚润求学6 小时前
【贪心算法】day8
c++·算法·leetcode·贪心算法
平生不喜凡桃李6 小时前
C++ 异常
android·java·c++
小伟童鞋6 小时前
c++中导出函数调用约定为__stdcall类型函数并指定导出函数名称
开发语言·c++