Qt基础终结篇:从文件操作到多线程异步UI,深度解析核心要点
文章目录
- 前言
- 一、QFileDialog 文件对话框
- 二、QFileInfo 文件信息类
- 三、QFile 文件读写类
- 四、UI与耗时操作:避免UI卡顿与程序未响应
- 五、多线程
- 六、异步刷新与线程通信
- 总结
前言
上一篇文章,我们已经把qt的基础知识讲解的差不多了。本文我们将继续进行qt的学习,并且一口气把qt的基础知识讲解完。大家可以根据目录的指引来快速获取自己需要的知识和内容,那么文章就从这里开始吧。
一、QFileDialog 文件对话框
QFileDialog 是 Qt 框架中用于提供标准文件选择对话框的类。它允许用户选择一个文件进行打开(读取)或保存(写入)。
核心特点:
纯界面类: QFileDialog 本身不执行文件的实际读写操作。它只负责提供一个用户界面,让用户选择文件路径。一旦用户选择了文件,它会返回该文件的路径字符串,后续的文件操作(如打开、读取、写入)需要由应用程序自行处理。
静态方法: 最常用的文件选择功能通过其静态方法提供,这意味着你不需要创建 QFileDialog 的实例就可以直接调用它们。
常用静态函数:
QFileDialog 提供了方便的静态方法来弹出“打开文件”或“保存文件”的对话框。
- getOpenFileName() - 弹出“打开文件”对话框
功能: 允许用户选择一个已存在的文件进行打开(通常是读取)。
QString QFileDialog::getOpenFileName(QWidget * parent = 0,const QString & caption = QString(),const QString & dir = QString(),const QString & filter = QString()
) [static]
返回值:
如果用户选择了一个文件并点击“打开”,则返回所选文件的完整路径字符串。
如果用户取消了对话框(例如点击“取消”按钮或关闭窗口),则返回一个空字符串。
- getSaveFileName() - 弹出“保存文件”对话框
功能: 允许用户指定一个文件路径来保存数据。用户可以选择一个现有文件进行覆盖,或者输入一个新文件名来创建新文件。
QString QFileDialog::getSaveFileName(QWidget * parent = 0,const QString & caption = QString(),const QString & dir = QString(),const QString & filter = QString()
) [static]
返回值:
如果用户指定了一个文件路径并点击“保存”,则返回所指定文件的完整路径字符串。
如果用户取消了对话框,则返回一个空字符串。
参数详解(适用于 getOpenFileName 和 getSaveFileName):
QWidget * parent = 0
类型: QWidget 指针
作用: 指定文件对话框的父窗口。
影响:
如果指定了父窗口,对话框将以模态(modal)方式显示,并居中于父窗口。这意味着用户必须先关闭文件对话框才能与父窗口进行交互。
如果为 0(默认值),对话框将作为顶级窗口显示,并且可能不会居中于任何特定窗口。
建议: 强烈建议指定父窗口,以提供更好的用户体验和窗口管理。
const QString & caption = QString()
类型: QString
作用: 设置文件对话框的标题栏文本。
默认值: 空字符串,此时系统会提供默认标题(例如“打开文件”或“保存文件”)。
示例: “选择图片文件”,“保存文档”
const QString & dir = QString()
类型: QString
作用: 指定对话框打开时最初显示的目录路径。
默认值: 空字符串,此时对话框通常会从应用程序的当前工作目录(或用户上次访问的目录,取决于操作系统和Qt版本)开始。
示例: “C:/Users/YourName/Documents”,“/home/user/images”
注意: 如果指定的目录不存在,对话框可能会回退到默认行为。
const QString & filter = QString()
类型: QString
作用: 定义文件类型过滤器,用于限制用户可以看到和选择的文件类型。
默认值: 空字符串,表示显示所有文件类型。
格式: 过滤器字符串由一个或多个过滤器项组成,每个项的格式为:“描述 (.扩展名1 .扩展名2);;描述2 (.扩展名3)"
描述: 用户在下拉菜单中看到的文本。
.扩展名: 匹配的文件扩展名。可以使用通配符 。
;;: 用于分隔多个过滤器项。
示例:
"图片文件 (.png .jpg .jpeg);;文本文件 (.txt);;所有文件 (.)"
"C++ 源文件 (.cpp .h);;Qt 项目文件 (.pro)”
注意: 过滤器只影响显示的文件,用户仍然可以通过手动输入文件名来选择不符合过滤器的文件(在某些操作系统上)。
代码示例
代码包
二、QFileInfo 文件信息类
QFileInfo 类用于获取文件的各种信息,例如文件是否存在、文件大小、上次修改时间等。它提供了多种成员函数来访问这些属性。
构造函数
QFileInfo::QFileInfo(const QString &file)
参数: file - 文件的完整路径(包括文件名)。
说明: 使用指定的文件路径构造一个 QFileInfo 对象。在构造之后,你可以使用该对象的成员函数来查询文件的各种属性。
常用成员函数
bool QFileInfo::exists() const
返回值: 如果文件或目录存在,则返回 true;否则返回 false。
说明: 用于检查由 QFileInfo 对象表示的文件或目录是否存在于文件系统中。
qint64 QFileInfo::size() const
返回值: 文件的字节大小。如果文件不存在或无法访问,则返回 0。
说明: 返回文件的大小,单位是字节。对于目录,此函数通常返回 0。
QDateTime QFileInfo::lastModified() const
返回值: 一个 QDateTime 对象,包含文件的上次修改日期和时间。如果文件不存在或无法访问,则返回一个无效的 QDateTime 对象。
说明: 获取文件的最后修改时间戳。QDateTime 对象可以进一步格式化或用于时间比较。
代码示例
代码包
三、QFile 文件读写类
QFile类是Qt中用于文件操作的核心类,它间接继承自QIODevice类。QIODevice类是Qt所有IO类的基类,提供了许多读写的基础接口。
核心功能概述
QFile提供了方便的文件创建、打开、读写和关闭操作。它通过其基类QIODevice继承了通用的IO操作接口,并为文件系统特有的行为(如文件路径、权限等)提供了封装。
相关函数
以下是QFile和其基类中常用的一些函数:
- 构造函数
QFile::QFile(const QString & name)
作用: 构造一个QFile对象。
参数: name (const QString &) - 指定要操作的文件的路径和名称。
备注: 构造函数只是创建了QFile对象并设置了文件路径,并不会立即打开文件。
- 文件流操作
bool QIODevice::open(OpenMode mode)
作用: 打开文件流。这是在读写文件之前必须调用的函数。
参数: mode (OpenMode) - 指定打开文件的模式。OpenMode是一个枚举类型,可以组合使用(例如:QIODevice::ReadOnly | QIODevice::Text)。
常用模式举例:
QIODevice::ReadOnly: 只读模式。文件必须存在。
QIODevice::WriteOnly: 只写模式。如果文件不存在则创建,如果存在则清空内容。
QIODevice::ReadWrite: 读写模式。
QIODevice::Append: 追加模式。写入的数据会添加到文件末尾。
QIODevice::Truncate: 清空模式。打开文件时会清空文件内容。
QIODevice::Text: 文本模式。在Windows上,将\r\n转换为\n,反之亦然。
返回值: bool - 如果成功打开文件则返回true,否则返回false。
备注: 建议在使用后检查返回值,以确保文件成功打开。
void QIODevice::close()
作用: 关闭文件流。释放文件资源。
备注: 在文件操作完成后,务必调用此函数来关闭文件,以避免资源泄露或数据丢失。
- 数据读取
QByteArray QIODevice::read(qint64 maxSize)
作用: 从文件流中读取指定最大字节数的数据。
参数: maxSize (qint64) - 要读取的最大字节数。
返回值: QByteArray - 包含读取到的数据的字节数组。如果达到文件末尾或发生错误,返回的QByteArray可能小于maxSize或为空。
备注: 该函数会尝试读取最多maxSize个字节,但可能因为文件剩余内容不足或到达文件末尾而读取更少的数据。
qint64 QIODevice::bytesAvailable() const
作用: 返回流中当前可供读取的剩余字节数。
返回值: qint64 - 可用的字节数。
备注: 在读取文件时,可以使用此函数来判断是否还有数据可读,或者一次性读取所有剩余数据。
- 数据写入
qint64 QIODevice::write(const QByteArray & byteArray)
作用: 将QByteArray中的数据写入文件流。
参数: byteArray (const QByteArray &) - 要写入的数据。
返回值: qint64 - 实际写入的字节数。如果发生错误,可能返回-1或小于byteArray.size()的值。
备注: 在写入后,应检查返回值以确保所有数据都已成功写入。
- 缓冲区操作
bool QFileDevice::flush()
作用: 清空文件设备的内部写缓冲区,将所有缓存的数据强制写入底层设备(例如硬盘)。
返回值: bool - 如果刷新成功则返回true,否则返回false。
备注: 写入操作通常是先写入内存缓冲区,再由操作系统或文件系统异步写入磁盘。flush()可以强制将数据立即写入磁盘,这在确保数据持久性(例如在关键操作后或程序退出前)时非常有用。
代码示例
代码包
四、UI与耗时操作:避免UI卡顿与程序未响应
- 主线程(UI线程)的职责:
程序启动时,默认只有一个线程,即主线程(也称为UI线程)。
主线程的核心职责是处理所有Qt基础事件和UI操作,确保用户界面的流畅响应。
- 耗时操作对主线程的影响:
当耗时较长的操作(例如:读写大文件、复杂的计算、网络请求等)在主线程中执行时,主线程会被这些操作“占用”或“阻塞”。
被阻塞的主线程无法及时处理UI事件(如点击、滚动、窗口重绘等),导致用户界面出现卡顿、假死现象。
如果阻塞时间过长,操作系统会认为程序失去了响应,并可能弹出“程序未响应”的提示窗口,严重影响用户体验。
- 解决方案:分离耗时操作到子线程:
为了保持UI的流畅和程序的响应性,解决卡顿问题的根本方法是:将所有耗时较长的操作从主线程中分离出来。
这些耗时操作应该被移到独立的“子线程”中执行。
子线程在后台默默工作,而主线程则继续专注于UI事件的处理,从而确保用户界面的持续响应和良好的用户体验。
五、多线程
QThread 类是 Qt 提供的用于多线程编程的类。它封装了平台相关的线程API,提供了一个方便、跨平台的接口来创建和管理线程。
QThread 类核心函数:
void QThread::msleep(unsigned long msecs) [static]
描述: 强制当前线程睡眠 msecs 毫秒。这是一个静态函数,可以在任何线程中调用,使该线程进入休眠状态。常用于模拟耗时操作。
void QThread::run() [virtual protected]
描述: 这是子线程的起始点。当你调用 QThread::start() 函数后,QThread 内部会自动调用这个 run() 函数。你需要继承 QThread 类并覆盖(override)这个函数,将所有需要在子线程中执行的耗时操作放在这个 run() 函数的实现中。
void QThread::start(Priority priority = InheritPriority) [slot]
描述: 启动子线程。调用此函数后,QThread 会创建一个新的操作系统线程,并在该线程中执行你的 run() 函数。priority 参数可以设置线程的优先级,通常保持默认即可。
创建并开启一个子线程的详细步骤:
在Qt Creator中创建新的C++ Class文件:
在Qt Creator的“项目”视图中,右键点击你的项目名称。
选择“添加新文件…”。
在弹出的对话框中,选择“C++ Class”。
配置类信息:
通常会提示你输入类名、基类等信息。
类名: 例如 MyThread (你可以根据自己的需求命名)。
基类 (Base Class): 选择 QThread。
确保勾选“头文件”和“源文件”的选项,Qt Creator会自动为你生成 mythread.h 和 mythread.cpp (如果你的类名是MyThread)。
完成类创建:
直接点击“完成”按钮。现在你的项目中会多了 mythread.h 和 mythread.cpp 两个文件。
代码示例
代码包
六、异步刷新与线程通信
在实际开发中,特别是涉及到用户界面(UI)的应用,异步刷新是一个至关重要的概念。它解决了在UI线程上执行耗时操作所导致的界面冻结问题。而实现异步刷新的核心,就是主线程和子线程之间的通信。
- 为什么需要异步刷新?
主线程不能执行耗时操作:
主线程(通常也称为UI线程)负责处理用户交互、绘制UI界面等任务。
如果主线程执行耗时操作(如网络请求、数据库查询、大文件读写、复杂计算),它会被阻塞,导致UI无响应、用户体验极差,甚至可能被操作系统判定为“应用程序无响应”(ANR)。
UI操作是线程不安全的: 多数UI框架(如Android的View体系,Java Swing/AWT,.NET WinForms/WPF)规定,所有对UI组件的修改必须在主线程上执行。这是为了避免并发访问UI组件时出现数据不一致或绘制错误。
子线程不能执行UI操作:
子线程的创建是为了执行耗时操作,从而不阻塞主线程。
直接在子线程中操作UI组件会导致应用程序崩溃、行为异常或不可预测的UI状态。
- 线程通信的本质:父对象与子对象的通信
正如内容中提到的,“主线程往往是子线程的父对象,因此线程通信问题本质上就是父对象和子对象的通信问题。”这是一种非常形象且准确的理解。
子线程(“子对象”)执行任务并报告结果: 子线程启动后,执行它的耗时任务。任务完成后,它需要将结果(或者任务完成的状态)通知给主线程。
主线程(“父对象”)接收通知并更新UI: 主线程接收到子线程的通知后,根据通知的内容,在主线程上执行相应的UI更新操作。
代码示例
代码包
示例:多线程文件拷贝器
代码包
总结
本文作为Qt基础知识的“终结篇”,系统地梳理并深入讲解了Qt应用程序开发中的几个关键模块:QFileDialog文件对话框、QFileInfo文件信息类、QFile文件读写类,以及至关重要的多线程编程。文章首先详细介绍了如何使用QFileDialog进行文件选择,以及QFileInfo获取文件元数据。随后,深入探讨了QFile的文件打开、读写操作及其缓冲机制。为了解决UI卡顿和程序未响应问题,文章重点阐述了多线程的必要性,详细讲解了QThread的使用方法,并强调了主线程与子线程间异步刷新和通信的本质。通过详细的理论解析和代码示例,旨在帮助读者掌握Qt中文件操作的实用技巧和多线程编程的核心思想,为构建响应迅速、用户体验良好的Qt应用打下坚实基础。
相关文章:
Qt基础终结篇:从文件操作到多线程异步UI,深度解析核心要点
文章目录 前言一、QFileDialog 文件对话框二、QFileInfo 文件信息类三、QFile 文件读写类四、UI与耗时操作:避免UI卡顿与程序未响应五、多线程六、异步刷新与线程通信总结 前言 上一篇文章,我们已经把qt的基础知识讲解的差不多了。本文我们将继续进行qt…...
ubuntu中,文本编辑器nano和vim区别,vim的用法
目录 一.区别1.介绍2.适用场景3. 配置与个性化1) nano:2)Vim: 二.Vim1、Vim 的安装与启动2、Vim 的三种模式 (普通模式、插入模式、命令行模式)3、Vim 的常用操作4、Vim 的配置5、Vim 的高级功能 三.nano使…...

山洪灾害声光电监测预警解决方案
一、方案背景 我国是一个多山的国家,山丘区面积约占国土面积的三分之二。每年汛期,受暴雨等因素影响,极易引发山洪和泥石流。山洪、泥石流地质灾害具有突发性、流速快、流量大、物质容量大和破坏力强等特点,一旦发生,将…...

【Rust模式与匹配】Rust模式与匹配深入探索与应用实战
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
React从基础入门到高级实战:React 高级主题 - React Concurrent 特性:深入探索与实践指南
React Concurrent 特性:深入探索与实践指南 引言 随着Web应用对用户体验的要求日益提高,React在2025年的技术环境中引入了并发渲染(Concurrent Rendering)这一革命性特性,旨在提升应用的响应速度和交互流畅度。并发渲…...

electron安装报错处理
electron安装报错 解决方法: 修改 C:\Users\用户名.npmrc下配置文件 添加代码 electron_mirrorhttps://cdn.npmmirror.com/binaries/electron/ electron_builder_binaries_mirrorhttps://npmmirror.com/mirrors/electron-builder-binaries/最后代码 registryhtt…...

NHANES指标推荐:CQI
文章题目:The impact of carbohydrate quality index on menopausal symptoms and quality of life in postmenopausal women 中文标题:碳水化合物质量指数对绝经后妇女更年期症状和生活质量的影响 发表杂志:BMC Womens Health 影响因子&…...
【OpenHarmony】【交叉编译】使用gn在Linux编译3568a上运行的可执行程序
linux下编译arm64可执行程序 一.gn ninja安装二.交叉编译工具链安装1.arm交叉编译工具2.安装arm64编译器 三. gn文件添加arm及arm64工具链四.编译验证 本文以gn nijia安装中demo为例,将其编译为在arm64(rk_3568_a开发板)环境下可运行的程序 一.gn ninja安装 安装g…...
Med-R1论文阅读理解-1
论文总结:Med-R1: Reinforcement Learning for Generalizable Medical Reasoning in Vision-Language Models 论文写了什么? 本文提出了一种名为 Med-R1 的新框架,旨在通过强化学习(Reinforcement Learning, RL)提升…...

【从零开始学习QT】快捷键、帮助文档、Qt窗口坐标体系
目录 Qt Creator 中的快捷键 使用帮助文档 Qt 窗口坐标体系 QT专栏:QT_uyeonashi的博客-CSDN博客 Qt Creator 中的快捷键 • 注释:ctrl / • 运行:ctrl R • 编译:ctrl B • 字体缩放:ctrl 鼠标滑轮 • 查找&am…...
强化学习笔记总结(结合论文)
本篇博客参考来自大佬的开源书籍,结合自己的思考,写了这一篇总结,帮助大家学习了解强化学习的基础知识 文章目录 强化学习特点定义 强化学习应用实例强化学习和监督式学习、非监督式学习分类强化学习和监督式学习的区别:强化学习…...
Java线程安全解决方案全面指南
Java线程安全解决方案全面指南 引言 在多线程编程中,线程安全是保证程序正确性的关键要素。Java作为一门广泛用于并发编程的语言,提供了丰富的线程安全解决方案。本文将全面介绍Java中实现线程安全的各类方法,帮助开发者编写出更健壮的多线…...
superior哥深度学习系列(大纲)
🚀 superior哥深度学习系列学习大纲(2025版) 嘿!各位AI探索者们!👋 这是superior哥精心打造的深度学习学习路线图。从零基础小白到AI实战高手,这份大纲会陪你一路成长!记住ÿ…...

基于stm32的多旋翼无人机(Multi-rotor UAV based on stm32)
由于一直在调试本项目,好久没有发文章,最近本项目的PID调试初见成效!开始正文前首先感谢各位粉丝的支持,以及对本项目技术上支持的老师以及师兄,谢谢你们! 对应源码及文件:源码及文件下载 基于…...

实验分享|基于sCMOS相机科学成像技术的耐高温航空涂层材料损伤检测实验
1实验背景 航空发动机外壳的耐高温涂层材料在长期高温、高压工况下易产生微小损伤与裂纹,可能导致严重安全隐患。传统光学检测手段受限于分辨率与灵敏度,难以捕捉微米级缺陷,且检测效率低下。 某高校航空材料实验室,采用科学相机…...

RAG混合检索:倒数秩融合RRF算法
文章目录 检索增强生成 (RAG)倒数秩融合在 RAG 中的工作原理RRF 背后的数学直觉检索增强生成 (RAG) RAG 是自然语言处理中的一种强大技术,结合了基于检索的模型和生成模型的优势。 如果检索器未能从检索器中获取相关文档,则精度较低,幻觉的可能性会增加。 有些查询适合…...

2011肠衣问题
1 D类竞赛题目---具体题目 D题 天然肠衣搭配问题 天然肠衣(以下简称肠衣)制作加工是我国的一个传统产业,出口量占世界首位。肠衣经过清洗整理后被分割成长度不等的小段(原料),进入组装工序。 传统的生产…...

RG3000网关构建5G LAN智慧工厂智能制造
在工业4.0与智能制造的趋势下,传统制造业正前后往智慧工厂转型升级。在转型过程中,高效、稳定、灵活的网络通信是实现设备互联互通、数据实时交互与智能决策的基础。智联物联RG3000网关,凭借其融合5G通信技术、WiFi6无线传输、边缘计算能力与…...
Rust语言学习教程、案例与项目实战指引
Rust语言学习教程、案例与项目实战指引 一、入门教程 (一)官方核心文档 Rust官方网站的核心文档是踏上Rust学习征程的绝佳起点。这里犹如一座知识宝库,涵盖了Rust编程时可能遇到的几乎所有内容,从基础语法到高级特性,一…...
通信应用高速模数转换器ADC
在5G通信、医疗成像、航空航天及工业自动化等关键领域,高速ADC模数转换器作为信号链的“心脏”,其性能直接决定了系统的精度与效率。然而,如何精确测试高速ADC的动态参数、优化设计验证流程、应对复杂应用场景的挑战,始终是工程师…...
大模型测评选型指南:企业级大模型测评实战解析
在当今数字化飞速发展的时代,AIGC大模型如雨后春笋般涌现,为各行业带来创新变革的同时,其安全性也成为了不容忽视的关键问题。随着人工智能技术加速落地,AIGC大模型的安全合规已成为产业发展的核心命题。那么,企业该如…...
微信小程序学习目录
个人简介 👨💻个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言&…...
AG32 DMAC实现内部MCU与FPGA通信【知识库】
一、简介 DMAC是独立于MCU和FPGA之外的外设,连接到AHB总线,可通过寄存器配置实现直接内存存取。通过AHB总线实现MCU与FPGA进行高性能通信。理论最高传输速率可达 bus_clock * 32 168MHz * 32 5376Mbps 5.25Gbps,超频到336MHz的形况下&…...

webrtc初了解
1. webrtc的简介 一、WebRTC 是什么? Web Real-Time Communication(网页实时通信),是浏览器原生支持的实时音视频通信技术,无需安装插件或客户端,可直接在浏览器之间实现点对点(P2P)…...

[STM32学习笔记(九)]CubeMX项目使用系统定时器SysTick的中断服务函数进行定时
有很多文章说明了由于HAL_Delay()函数的本质是系统定时器计数,通过全局变量uwTick的不断增加实现的比较延迟。调用HAL_Delay()函数会阻塞其他工作,因此在外设ISR进程调用该延迟时,要特别小心。 因此,现在考虑,既然系统…...
5G 核心网 NGAP UE-TNL 偶联和绑定
引言: 在 5G 核心网架构中,NG 接口作为连接无线接入网(RAN)与核心网(5GC)的关键纽带,承载着大量控制面信令交互。NG 应用协议(NGAP)作为 NG 接口上的核心协议,负责管理 RAN 与 5GC 之间的通信,其中 UE - TNL(User Equipment - Transport Network Layer)偶联和绑定…...
性能测试怎么做?方法、流程与核心要点解析
目录 一、性能测试核心方法论 性能测试五大类型解析 七项关键性能指标 二、性能测试实施流程 需求分析阶段 测试设计阶段 环境搭建要点 测试执行策略 三、性能问题定位与优化 常见瓶颈识别 优化实战案例 四、测试报告编写规范 核心内容框架 数据可视化建议 五、企…...

将ipynb文件转换为markdown格式文件
文章目录 将ipynb文件转换为markdown格式文件nbconvert 包安装nbconvert 使用 将ipynb文件转换为markdown格式文件 有时候,我们需要把Jupyter notebook的.ipynb格式文件转换为markdown格式.md,便于使用。 那么,我们可以通过安装nbconvert包&a…...

Vulnhub_Zico2_wp
一、信息收集 1、主机发现 arp-scan -l 2、端口扫描 nmap -sS -sV 192.168.66.144 nmap -p- -Pn -sC -sV -n 192.168.66.144 whatweb -v 192.168.66.144 这里开放了3个端口,先80端口拿去目录,然后测试下22端口有没有什么未授权之类的,然后…...

【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验
【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验 腾讯推出的系列AI产品:混元大模型、大模型图像创作引擎、大模型视频创作引擎、腾讯元宝,共同构成了一个强大的AI生态系统;凭借腾讯自研的大规模预训练技术和先进的自然语言处理、计…...