QT零基础入门教程

发布于:2025-09-16 ⋅ 阅读:(35) ⋅ 点赞:(0)

基础篇

第一章 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

#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 窗口(附字符模拟界面)

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

字符模拟界面:

+----------------------------------------+
|  布局示例                  [_] [□] [×]  |  标题栏(宽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

代码示例:

#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(发送者对象, &发送者类::信号名, 接收者对象, &接收者类::槽函数名);

参数说明:​

  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​

完整代码:

#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 通过 “事件队列” 管理事件。​

常用事件类型:​

  1. QMouseEvent:鼠标事件(点击、移动、滚轮);​
  2. QKeyEvent:键盘事件(按键按下、松开);​
  3. 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开发知识点梳理

后续更新