简介:《Qt5范例开发大全(完整目录版)》面向具备一定C++基础、希望系统掌握Qt5桌面开发的学习者与在职开发者,以实例驱动的方式覆盖从环境搭建到打包部署的完整链路。全书十四章依次展开开发环境与Qt Creator安装、窗体应用、控件应用、组件应用、文件操作、图形图像、多媒体、系统操作、注册表、数据库基础、网络开发、进程与线程、数据安全及打包部署,目录层级清晰,便于按模块检索与对照练习。资源包共1个PDF文件,大小约2.84MB,为完整目录版文档,适合作为案头查阅的范例索引与学习路线图。目前已有2460人学习下载,说明其在Qt5入门与进阶群体中具有一定参考价值。读者可借助书中对QPushButton、QLabel、QLineEdit、QComboBox、QTableView等常用控件及布局管理的实例讲解,快速建立界面开发思路,并延伸到文件、网络、多线程等实际场景,逐步具备独立开发Qt5应用的能力。
1. 一份按目录就能查的 Qt5 范例手册,到底值不值得放在手边
接手一个 Qt5 老项目做维护,最耗时间的往往不是写业务逻辑,而是“这个控件怎么设成只读”“无边框窗体怎么拖”“INI 文件读写用哪个类”这类具体到 API 的问题。翻官方文档要英文、要跳转,搜出来的博客又常常是 Qt4 时代的写法。这份《Qt5范例开发大全(完整目录版)》的定位就很清楚:它是一本按功能点组织的 C++ Qt5 范例目录,从开发环境、窗体、控件、组件,一路排到文件操作、图形图像、多媒体、系统操作、注册表、数据库、网络、进程线程、数据安全和打包部署,十四章覆盖了桌面端开发最常碰到的场景。适合谁?刚上手 Qt5 的 C++ 开发者拿它当练手清单,以及需要快速查某个控件或模块最小可用写法的在职工程师。它不教你架构,但能让你少在“这个类叫什么”上耗时间。
2. 开发环境与第一个可运行工程:从安装到 Hello World 的完整链路
2.1 为什么先锁定 Qt5 + MinGW 这套组合
范例正文里明确针对 Windows 环境,用的是 Qt5.1.1 for Windows 32-bit(MinGW 4.8、OpenGL)这个离线包。这个选择在今天看不算新,但对照着范例复现的人来说反而是好事:MinGW 版本自带编译器,不需要额外装 Visual Studio,装完就能编译,环境变量配好之后双击 exe 也能直接跑。很多新手翻车的点在于装了在线安装器却只勾了 Qt 库没勾编译器,结果新建工程一编译就报“No compiler found”。所以第一步不是急着写代码,而是确认安装包里带了 MinGW 那一项。
安装完成后要配环境变量,把 Qt 的 bin 目录加进系统 Path,范例里给的路径形如D:\Qt\Qt5.1.1\5.1.1\mingw48_32\bin。这一步的意义在于:编译出来的 exe 依赖 Qt 的动态库,Path 里有 bin 目录,双击 exe 才能找到 dll,否则就是经典的“缺少 Qt5Core.dll”弹窗。注意路径前面那个分号别漏,它是 Windows 环境变量的分隔符。
# 检查 Qt 的 bin 目录是否已在 Path 中(Windows CMD) where qmake # 正常应输出类似: # D:\Qt\Qt5.1.1\5.1.1\mingw48_32\bin\qmake.exewhere qmake能定位到 qmake,说明环境变量生效了。如果输出“找不到”,要么路径写错,要么改完环境变量没重开终端——这是血泪经验里最常见的一条,改完 Path 必须关掉所有 CMD 和 Qt Creator 重新打开,否则读的还是旧环境。
2.2 新建工程时三个基类怎么选
范例在创建项目那一步专门讲了 QMainWindow、QWidget、QDialog 三个基类的区别,这个点值得单独拎出来说,因为选错了后面改起来很别扭。QMainWindow 自带菜单栏、工具栏、状态栏和中央部件区,适合做主窗口;QWidget 是所有界面对象的基类,最轻,适合做自定义控件或简单窗口;QDialog 是对话框基类,支持模态/非模态和返回值,适合做登录框、设置页这类短期交互。
我的习惯是:不确定就选 QWidget,需要菜单栏再换 QMainWindow,需要“确定/取消”返回值就用 QDialog。范例里 Hello World 用的是在 MainWindow 上挂一个 QLabel,核心代码就几行:
// mainwindow.cpp 关键片段 #include "mainwindow.h" #include <QLabel> // 引用标签控件类 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QLabel *label = new QLabel(this); // 实例化 QLabel,父对象为当前窗体 label->setText("Hello World"); // 设置显示内容 label->setGeometry(QRect(50, 50, 200, 30)); // x, y, 宽, 高 }setGeometry的四个参数依次是相对父窗体的 X、Y 坐标和控件宽高,这是绝对定位写法,做练习够用,正式界面还是建议上布局。new QLabel(this)里的this很关键,它把控件挂到窗体对象树上,窗体销毁时子控件自动释放,这就是 Qt 的对象树回收机制,范例里也点到了“用完实例后释放内存”这层意思。新手常犯的错是new了不指定父对象又不手动delete,跑久了就是内存泄漏。
2.3 工程目录里哪些文件是自动生成的
范例提到 debug 和 release 两个文件夹是根据构建配置自动生成的,里面放编译产物。这一点对排查问题有用:如果改了代码但运行结果没变,先看是不是跑到了旧的构建目录;如果想把工程发给别人,debug/release 和.user文件都不该带,只留.pro、头文件、源文件和资源文件即可。.pro是 qmake 的工程描述文件,加模块、加资源都在这改,比如要用网络模块就得在.pro里补QT += network,忘了这行就是编译期一堆“未定义”错误。
3. 窗体与控件:把界面骨架搭起来的可复现写法
3.1 窗体大小、位置、背景色与图标
窗体这一章是 Qt5 界面开发的地基,范例给的几个例子都很短,但每个都对应一个真实需求。控制窗体固定 300x300,用的是setMaximumSize和setMinimumSize同时设成一样,最大最小相等,用户就拖不动了。初始位置用move(100, 100),背景色用样式表setStyleSheet("background:red")。这里有个细节:样式表设背景色对 QMainWindow 有时不生效,因为主窗口的中央部件盖在上面,常见做法是给 centralWidget 设样式,或者改用 QWidget 做基类。
改标题栏图标要先准备一张 16x16 的 ICO,然后走 Qt 资源系统:新建.qrc资源文件,添加前缀、添加文件、给文件起别名,最后在代码里用setWindowIcon(QIcon(":/new/prefix1/ico"))引用。资源路径的冒号开头表示从编译进二进制的资源里取,不依赖外部文件,打包时省心。别名起成ico之后,路径里就不用写.ico后缀,这一点范例特意提醒了,写全名反而找不到。
3.2 无边框窗体拖动的三个鼠标事件
去掉标题栏之后窗体就没法拖了,范例用setWindowFlags(Qt::FramelessWindowHint)去掉边框,再自己实现鼠标按下、移动、释放三个事件来补上拖动能力。这段代码是很多人第一次接触 Qt 事件机制的入口,值得逐行看:
// mainwindow.h 中声明 protected: void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; private: QPoint last; // 记录上一次的全局鼠标位置 // mainwindow.cpp 中实现 void MainWindow::mousePressEvent(QMouseEvent *e) { last = e->globalPos(); // 按下时记录全局坐标 } void MainWindow::mouseMoveEvent(QMouseEvent *e) { int dx = e->globalX() - last.x(); // 计算横向位移 int dy = e->globalY() - last.y(); // 计算纵向位移 last = e->globalPos(); // 更新基准点 move(x() + dx, y() + dy); // 窗体跟着移动 } void MainWindow::mouseReleaseEvent(QMouseEvent *e) { int dx = e->globalX() - last.x(); int dy = e->globalY() - last.y(); move(x() + dx, y() + dy); }用globalPos而不是pos是关键:pos是相对控件左上角的坐标,窗体一移动基准就乱了,拖动会抖;全局坐标不受窗体位置影响,位移算出来才稳。move(x()+dx, y()+dy)里的x()、y()是窗体当前左上角坐标。去掉标题栏后关闭按钮也没了,范例的做法是自己加一个 QPushButton 连到close()槽,这个思路可以推广到最小化、最大化按钮的自绘。
3.3 控件清单怎么当查询表用
控件这一章列了二十多个控件,从 QPushButton、QLabel、QLineEdit 到 QComboBox、QSpinBox、QTimeEdit、QDateEdit,再到 QListView、QTreeView、QTableView 和 QHBoxLayout、QGridLayout 两种布局。这份清单的价值不在通读,而在当索引:需要日期选择就翻 QDateEdit,需要下拉就翻 QComboBox,需要表格展示就翻 QTableView。范例对每个控件给的是最小可运行片段,比如 QLineEdit 设只读、QSpinBox 设范围、QTableView 配模型,都是能直接抄进工程的量级。
布局这块要提醒一句:QHBoxLayout 横向排、QGridLayout 按行列摆,两者可以嵌套。新手容易全用绝对定位setGeometry,窗口一缩放控件就错位;正确姿势是顶层用布局管理器,局部需要精确控制的地方再绝对定位。范例里 QGroupBox 和 QTabWidget 的例子也值得看,分组框和选项卡是组织复杂界面的常用容器,配合布局能少写很多坐标计算。
4. 文件、图形与系统操作:跨模块的落地细节
4.1 文件读写与 INI、XML 配置
文件操作这一章覆盖创建文件夹、写入、修改、删除、重命名,以及 INI 和 XML 的读写。桌面工具类项目里,配置文件用 INI 最省事,Qt 的 QSettings 直接支持。范例给的 INI 写入读取流程,核心就是构造 QSettings 对象、setValue写、value读:
#include <QSettings> // 写入 INI QSettings settings("config.ini", QSettings::IniFormat); settings.setValue("user/name", "tester"); // 分组/键 = 值 settings.setValue("user/level", 3); // 读取 INI QString name = settings.value("user/name").toString(); int level = settings.value("user/level", 1).toInt(); // 第二个参数是默认值QSettings::IniFormat指定按 INI 格式解析,不指定的话 Windows 上默认写注册表,跨平台行为不一致。value的第二个参数是缺省值,配置项不存在时返回它,比先判断contains再取值更简洁。XML 那部分用 QDomDocument 建树、写文件、解析,适合结构比 INI 复杂的配置,但代码量明显更大,简单场景没必要上。
4.2 图形图像:绘制、缩放、翻转与特效
图形图像这一章从绘制文字、线条、椭圆,到显示静态/动态图像、水平移动、翻转、缩放、图上加文字,再到扭曲、模糊、着色、阴影、透明这些特效。绘制类操作基本都在paintEvent里用 QPainter 完成,图像特效则多用 QImage 的像素操作或 QGraphicsEffect。以图片缩放为例,常见写法是QPixmap::scaled指定目标尺寸和缩放模式:
QPixmap pix(":/images/demo.png"); // 按目标宽高缩放,保持宽高比用 Qt::KeepAspectRatio QPixmap scaled = pix.scaled(200, 150, Qt::KeepAspectRatio, Qt::SmoothTransformation); label->setPixmap(scaled);Qt::SmoothTransformation是平滑缩放,缩小图片时比默认的快速变换好看很多,代价是稍慢;做缩略图列表时这个参数值得开。翻转用 QTransform 的scale(-1, 1)做水平镜像,旋转用rotate。模糊、阴影这类效果,Qt5 里可以用 QGraphicsBlurEffect、QGraphicsDropShadowEffect 挂到控件上,比手写卷积省事,但注意特效会走图形渲染路径,控件多了性能会掉。
4.3 系统操作、注册表与数据库
系统操作章里有获取屏幕分辨率、本机名和 IP、根据网址解析 IP、判断按键键值、读环境变量、执行系统命令。执行系统命令用 QProcess,这是 Qt 里调外部程序的标准做法,比system()可控,能拿到输出和退出码。注册表操作在 Windows 上通过 QSettings 的 NativeFormat 完成,范例里改浏览器默认主页那个例子就是写注册表键值,这类操作要谨慎,改之前最好先读原值备份。
数据库章从查驱动、QODBC 连 Access,到插入、列表、操作 SQLite、SQLite 视图管理器。SQLite 是 Qt 自带驱动,不用额外装,适合做本地存储。连接流程是QSqlDatabase::addDatabase("QSQLITE")、setDatabaseName、open,然后 QSqlQuery 执行 SQL。注意addDatabase的第二个参数是连接名,多连接场景要区分,用完close并从QSqlDatabase::removeDatabase移除,否则会有连接泄漏警告。
5. 网络、线程与打包:从能跑到能交付
5.1 点对点聊天与 SMTP 发邮件
网络章给了点对点聊天服务端和客户端、局域网广播聊天、SMTP 发邮件、调系统 DLL 判断网络状态。点对点聊天用 QTcpServer 监听、QTcpSocket 收发,服务端listen一个端口,客户端connectToHost,收到数据走readyRead信号。局域网广播用 QUdpSocket 的广播地址,适合做设备发现。SMTP 发邮件这块要注意,范例年代的写法多是明文或简单认证,现在多数邮件服务要求加密连接,直接照抄可能连不上,得按服务商要求补 TLS 配置,这是照着老范例复现时最容易翻车的地方之一。
5.2 QThread 与 QRunnable 两种线程写法
进程与线程章讲了进程管理器和 QThread、QRunnable 两种线程用法。QThread 适合需要长期运行、带自己事件循环的任务,继承 QThread 重写run是常见写法;QRunnable 配合 QThreadPool 适合一次性短任务,扔进线程池自动调度,不用自己管线程生命周期。选型上,任务多且短用线程池,任务少且长用 QThread。无论哪种,UI 更新都必须回到主线程,跨线程直接操作控件是经典崩溃源,正确做法是用信号槽的队列连接把结果传回主线程。
5.3 数据安全与打包部署
数据安全章有 QByteArray 加密、AES 加密、MD5、生成随机数。要强调一点:MD5 是摘要不是加密,不能用来存密码,范例里把它归在“加密数据”下是当年的习惯叫法,实际用的时候密码存储应该用带盐的慢哈希。AES 加密要注意密钥和 IV 的管理,硬编码在代码里等于没加密。打包部署章给了 FilePacker 和 Inno Setup 两种方式,前者做自解压包,后者做标准 Windows 安装程序。Qt 程序打包的核心是把依赖的 dll 一起带上,常见做法是用windeployqt自动收集:
# 在 release 构建目录下执行,自动拷贝依赖的 Qt dll 和插件 windeployqt.exe MyApp.exewindeployqt会扫描 exe 的依赖,把 Qt5Core、Qt5Gui、Qt5Widgets 以及 platforms 插件等拷到同目录,省去手动找 dll 的麻烦。漏了 platforms 插件就是“程序启动报找不到 windows 平台插件”,这是打包环节最高频的坑。
6. 避坑与排查:照着范例复现时最容易翻车的五处
6.1 编译报“No compiler found”
现象是新建工程点构建直接失败,提示没有可用编译器。原因多半是安装时只勾了 Qt 库没勾 MinGW 套件,或者装了但 Qt Creator 的套件配置里编译器路径没识别到。解决是回到安装器补装 MinGW 组件,然后在 Qt Creator 的“工具-选项-构建和运行”里检查套件,编译器、调试器、Qt 版本三项都要对上,缺一项就手动指定路径。
6.2 双击 exe 提示缺少 Qt5Core.dll
现象是 Qt Creator 里能跑,拷到别的机器或直接双击就报缺 dll。原因是运行环境找不到 Qt 的动态库,开发机能跑是因为 IDE 注入了环境。解决有两条路:把 Qt 的 bin 目录加进系统 Path,或者用windeployqt把依赖 dll 拷到 exe 同目录。发布给别人的程序必须走第二条,不能指望对方机器装了 Qt。
6.3 无边框窗体拖动时抖动或拖不动
现象是拖动窗体时位置乱跳,或者鼠标移出窗体就失去响应。原因通常是用了pos()而不是globalPos()做基准,或者鼠标事件没在头文件里正确声明为protected导致没被重写。解决是统一用全局坐标算位移,并确认三个事件函数的签名和override声明正确;另外拖动逻辑只应在按下状态生效,可以加一个bool m_dragging标志位控制,避免没按键时移动鼠标也触发。
6.4 样式表设背景色不生效
现象是给 QMainWindow 调setStyleSheet("background:red")后窗口还是灰的。原因是主窗口的中央部件覆盖在上面,样式没传到子部件。解决是给centralWidget()设样式,或者在样式表里写QMainWindow { background: red; }并确保没有子部件铺满。QWidget 子类要支持样式表背景,还得重写paintEvent或用setAttribute(Qt::WA_StyledBackground),否则样式表只对部分控件生效。
6.5 跨线程更新 UI 导致崩溃
现象是工作线程里直接label->setText(...),程序偶发崩溃或界面卡死。原因是 Qt 的控件不是线程安全的,只能在主线程操作。解决是把结果通过信号发回主线程,用Qt::QueuedConnection连接,让槽函数在主线程执行。排查这类问题可以开QT_FATAL_WARNINGS环境变量,让线程相关的警告直接中断,比偶发崩溃好定位。
7. 把范例目录变成自己的查询表:一个可复用的验证习惯
这份资料最大的用法不是从头读到尾,而是把它当成一张按功能点索引的查询表,配合一个固定的验证动作:每抄一个范例片段,先在一个空白工程里单独跑通,再往项目里搬。我一般会建一个叫qt5-lab的临时工程,.pro里把常用模块一次性加上:
QT += core gui widgets network sql xml multimedia这样不管翻到网络、数据库还是多媒体的例子,都不用反复改.pro重新构建。跑通之后,把关键参数记在一张自己的对照表里,比翻书快:
| 需求 | 关键 API | 容易漏的参数 |
|---|---|---|
| 固定窗体大小 | setMaximumSize / setMinimumSize | 两者要设成相同值 |
| 无边框拖动 | FramelessWindowHint + 鼠标事件 | 用 globalPos 而非 pos |
| 资源图标 | QIcon(":/前缀/别名") | 别名不带后缀 |
| INI 读写 | QSettings + IniFormat | 不指定格式会写注册表 |
| 发布依赖 | windeployqt | 别漏 platforms 插件 |
这张表是我踩过几轮坑之后攒下来的,每次接新项目先过一遍,能省掉大半低级错误。还有一点:范例里的代码是 Qt5 早期写法,部分 API 在新版本里有更推荐的替代,比如信号槽连接现在更推荐新式语法connect(sender, &Class::signal, receiver, &Class::slot),编译期就能检查签名是否匹配,比老的SIGNAL/SLOT宏安全。照抄范例时遇到编译警告,先查是不是这类过时写法,别急着怀疑环境。
从那以后我每次拿到一份范例型资料,都强制自己先跑通最小工程、再建对照表、最后才往业务里搬,三步缺一步就容易在别人的代码和自己的环境之间来回折腾。希望帮到你。
本文还有配套的精品资源,点击获取