【QT】Qt文件和多线程

个人主页~
Qt系统内容
- 一、Qt文件
- 1、文件读写
- 读
- 写
- 2、文件和目录信息
- 二、多线程
- 1、线程使用
- timethread.h
- widget.h
- timethread.cpp
- widget.cpp
- 2、线程安全
- (1)互斥锁
- QMutex
- QMutexLocker
- 一个例子
- mythread.h
- mythread.cpp
- widget.cpp
- QReadWriteLocker、QReadLocker、QWriteLocker
- (2)条件变量
- (3)信号量
一、Qt文件
对于Qt文件QFile的相关关系都在下面这个思维导图里面了,它的父类是QFileDevice,爷爷类是QIODevice,Qt中所有的输入输出的类都是继承自QIODevice,其中也包括网络IO、串口IO、蓝牙IO等

1、文件读写
对于文件的操作主要有读数据、写数据、关闭文件
| 操作 | 说明 |
|---|---|
| QIODevice::NotOpen | 没有打开设备 |
| QIODevice::ReadOnly | 以只读方式打开设备 |
| QIODevice::WriteOnly | 以只写方式打开设备 |
| QIODevice::ReadWrite | 以读写方式打开设备 |
| QIODevice::Append | 以追加方式打开设备,数据将写到文件末尾 |
| QIODevice::Truncate | 每次打开文件后重写文件内容,原内容将被删除 |
| QIODevice::Text | 在读⽂件时,行尾终止符会被转换为’\n’,当写入⽂件时,行尾终止符会被转换为本地编码,如Win32上为’\r\n’; |
| QIODevice::Unbuffered | 无缓冲形式打开文件,绕过设备中的任何缓冲区 |
| QIODevice::NewOnly | 文件存在则打开失败,不存在则创建文件 |
读
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton,&QPushButton::clicked,[=](){//获得文件路径QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\14725\\Desktop");//将路径设置为lineEdit的内容ui->lineEdit->setText(path);//通过path路径打开文件QFile file(path);//以只读方式打开文件file.open(QIODevice::ReadOnly);//读取所有的内容存在str字符串中QString str = file.readAll();//将字符串放到textEdit中ui->textEdit->setText(str);file.close();});
}
qfile
写
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton,&QPushButton::clicked,[=](){QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\14725\\Desktop");ui->lineEdit->setText(path);QFile file(path);//以写方式打开文件file.open(QIODevice::Append);//写入的内容file.write("写进去的字");file.close();});
}
qfile_2
2、文件和目录信息
| 方法 | 说明 |
|---|---|
| isDir | 检查是否是目录 |
| isExecutable | 检查是否是可执行文件 |
| fileName | 获得文件名 |
| completeBaseName | 获取完整的文件名 |
| suffix | 获取文件后缀 |
| completeSuffix | 获取完整文件后缀 |
| size | 获取文件大小 |
| isFile | 判断是否为文件 |
| fileTime | 获取文件的创建时间、修改时间、最近访问时间等 |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\14725\\Desktop");QFileInfo fileinfo(path);//这里的.toUtf8().data()后缀主要为为了将字符串转化为C字符串,不加时输出为:"阿门.txt"//加上输出为:阿门.txt,会去掉引号qDebug() << "文件名:" << fileinfo.fileName().toUtf8().data();qDebug() << "后缀名:" << fileinfo.suffix().toUtf8().data();qDebug() << "文件大小:" << fileinfo.size();qDebug() << "文件路径:" << fileinfo.path().toUtf8().data();qDebug() << "是否为文件:" << fileinfo.isFile();qDebug() << "是否为目录:" << fileinfo.isDir();QDateTime time1 = fileinfo.fileTime(QFileDevice::FileBirthTime);qDebug() << "创建时间:" << time1.toString("yyyy-MM-dd hh:mm:ss").toUtf8().data();QDateTime time2 = fileinfo.lastModified();qDebug() << "上次修改时间:" << time2.toString("yyyy-MM-dd hh:mm:ss").toUtf8().data();
}
文件属性

程序输出

二、多线程
1、线程使用
在Qt中多线程的处理一般是通过QTread类来控制实现的,这部分的内容与Linux内容强相关,我在学习这一块的时候是没有学习过Linux的,所以我是通过0Linux的基础来写下这部分内容的
| API | 说明 |
|---|---|
| run | 线程入口函数 |
| start | 通过调用run开始执行线程,操作系统根据优先级判定,如果线程正在运行,则这个函数相当于没有 |
| currentTread | 返回一个指向管理当前执行线程的QTread指针 |
| isRunning | 判断线程是否正在运行 |
| sleep | 使程序休眠,单位为s,类似的函数:msleep单位为ms,usleep单位为us |
| wait | 阻塞线程,与此QTread对象关联的线程已经完成执行或者尚未启动都返回true,如果等待超时,返回false |
| terminate | 终止线程执行,通过操作系统的调度决定是否立即终止 |
| finished | 线程结束后发出该信号 |
创建一个自定义类timethread,继承自QThread,在ui上创建一个pushbutton和label
timethread.h
class TimeThread : public QThread
{Q_OBJECT;
public:TimeThread();//线程任务函数void run();
signals://声明信号函数void sendTime(QString Time);
};
widget.h
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
private slots:void showTime(QString Time);void on_pushButton_clicked();private:Ui::Widget *ui;//定义线程对象TimeThread t;
};
timethread.cpp
void TimeThread::run()
{while (1) {QString time = QTime::currentTime().toString("hh::mm::ss");//发送信号emit sendTime(time);sleep(1);//每一秒发送一次信号}
}
widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//当t每次sendTime的时候,触发showTimeconnect(&t,&TimeThread::sendTime,this,&Widget::showTime);
}Widget::~Widget()
{delete ui;
}void Widget::showTime(QString Time)
{//设置label的内容为时间ui->label->setText(Time);
}void Widget::on_pushButton_clicked()
{//开启线程t.start();
}
QTread
我们前面也说过,线程函数内部不允许操作ui图形界面,一般是用作数据处理的
connect函数有五个参数,第五个参数就是只有在多线程的时候才有意义,用于指定信号和槽的连接类型,同时影响信号的传递方式和槽函数的执行顺序
| 参数 | 说明 |
|---|---|
| Qt::AutoConnection | 根据信号和槽函数所在的线程自动选择连接类型,同一线程使用Qt::DirectConnection,不同线程使用Qt::UniqueConnection |
| Qt::DirectConnection | 信号发出时,槽函数会立即在同一线程中执行,适用于信号和槽在同一线程时 |
| Qt::QueuedConnection | 信号发出时,槽函数会被插入到接收对象所属的线程的事件队列中,等待下一次时间循环时执行,适用于信号和槽不在同一线程 |
| Qt::BlockingQueuedConnection | 信号发出时,发送信号的线程会被阻塞,直到槽函数执行完毕,适用于信号和槽不在同一线程 |
| Qt::UniqueConnection | 确保信号与槽之间唯一连接关系的标志,可以使用位或操作与上述四种一种连接类型组合使用,可以避免重复连接 |
2、线程安全
(1)互斥锁
互斥锁是一种保护和防止多个线程同时访问同一对象实例的办法,主要通过QMutex类来处理
QMutex
用于保护共享资源的访问,实现线程间的互斥操作,在多线程的环境下,通过互斥锁来控制对共享数据的访问,确保线程安全
QMutex mutex;
mutex.lock();//上锁//访问共享资源mutex.unlock();//解锁
QMutexLocker
可以简化对互斥锁的上锁解锁操作,避免忘记解锁导致死锁
QMutex mutex;
{QMutexLocker locker(&mutex);//作用域内自动上锁//访问共享资源...}//作用域结束自动解锁
一个例子
mythread.h
class MyThread : public QThread
{
public:MyThread(QObject* parent = nullptr);void run();private://定义全局变量static QMutex mutex;static int num;
};
mythread.cpp
void MyThread::run()
{while (1) {this->mutex.lock();//锁上//每有一个线程进来就打印线程以及递增的数字qDebug() << this <<" : " << this->num++;this->mutex.unlock();//解锁QThread::sleep(1);}
}
在这个代码块中,mutex.lock() 和 mutex.unlock() 手动管理互斥锁,每次打印完信息后立即释放锁,然后进行 QThread::sleep(1),由于锁已经释放,其他线程可以立即进入这段代码,导致线程的执行和打印信息可能是无序的
void MyThread::run()
{while (1) {QMutexLocker locker(&mutex);qDebug() << this <<" : " << this->num++;QThread::sleep(1);}
}
在这个代码块中,使用了 QMutexLocker 来管理锁,QMutexLocker 会在它的作用范围内自动锁定 mutex,并在 locker 离开作用域时(即循环的下一次迭代开始时)自动解锁,在这里,QThread::sleep(1) 位于锁的作用范围内,所以整个 sleep 期间锁不会释放,这样可以保证一次只有一个线程在运行这段代码,从而避免线程间的竞争
widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);MyThread* t1 = new MyThread(this);MyThread* t2 = new MyThread(this);t1->start();t2->start();
}
QReadWriteLocker、QReadLocker、QWriteLocker
QReadWriteLocker:读写锁类,用于控制读和写的并发访问
QReadLocker:读操作上锁,允许多个线程同时读取共享资源
QWriteLocker:写操作上锁,只允许一个线程写入共享资源
QReadWriteLock rwLock;//在读操作中使⽤读锁
{QReadLocker locker(&rwLock); //在作⽤域内⾃动上读锁//读取共享资源//...
}//在作⽤域结束时⾃动解读锁//在写操作中使⽤写锁
{QWriteLocker locker(&rwLock); //在作⽤域内⾃动上写锁//修改共享资源//...
}//在作⽤域结束时⾃动解写锁
(2)条件变量
因为在多线程编程中,某些线程需要等待某些条件满足才能执行,此时线程会使用锁的机制来阻塞其他线程,当条件满足时,等待条件的线程将被另一个线程唤醒
QWaitCondition是Qt框架提供的条件变量类,用于线程之间的通信和同步,在某个条件满足时等待或唤醒线程,用于线程的同步和协调
QMutex mutex;
QWaitCondition condition;//等待线程中
mutex.lock();//检查条件是否满足,不满足就等待
while (!conditionFullfilled())
{condition.wait(&mutex);//条件满足释放锁
}mutex.unlock();//------------------------------------------------------------------------------------//在改变条件的线程中
mutex.lock();
//改变条件
changeCondition();
condition.wakeAll(); //唤醒等待的线程mutex.unlock();
(3)信号量
QSemaphone是Qt框架提供的计数信号类,用于控制同时访问共享资源的线程数量,用于限制并发线程数量,用于解决一些资源有限的问题
QSemaphore semaphore(2); //同时允许两个线程访问共享资源//在需要访问共享资源的线程中
semaphore.acquire(); //尝试获取信号量,若已满则阻塞//访问共享资源
//...
semaphore.release(); //释放信号量
//在另⼀个线程中也要进行类似操作
今日分享就到这了~

相关文章:
【QT】Qt文件和多线程
个人主页~ Qt系统内容 一、Qt文件1、文件读写读写 2、文件和目录信息 二、多线程1、线程使用timethread.hwidget.htimethread.cppwidget.cpp 2、线程安全(1)互斥锁QMutexQMutexLocker一个例子mythread.hmythread.cppwidget.cpp QReadWriteLocker、QReadL…...
PN结如何实现不同反向耐压及达到高反向耐压
目录 1. PN结实现不同耐压值 2. PN如何达到高反向耐压 1. PN结实现不同耐压值 主要通过以下几个方面: • PN结设计:不同耐压值的二极管在PN结的设计上有所不同。通过调整PN结的宽度和深度,可以改变空间电荷区的大小,从而影响二极…...
【bug日志-水】解决本地开发下代理和url同名导致刷新404的问题
bug描述 在本地开发,并且路由是history的模式下,代理和url同名的情况下,刷新会404。 {path: /googleAds,//如果有个代理也叫googleAds,刷新时就会404name: googleAds,icon: sound,routes: [{path: /googleAds/GoogleAdsSettingPag…...
Hive面试题-- 查询各类型专利 top10 申请人及专利申请数
在数据处理中,尤其是涉及到专利信息等复杂数据时,Hive 是一个强大的工具。本文将详细介绍如何使用 Hive 查询语句来获取各类型专利 top10 申请人以及他们对应的专利申请数,以下是基于给定的 t_patent_detail 表结构的分析和查询步骤。 建表语…...
996引擎 - 活捉NPC
996引擎 - 活捉NPC 引擎触发 - 引擎事件(QF)事件处理模块 GameEvent测试文件参考资料 引擎触发 - 引擎事件(QF) cfg_game_data 配置 ShareNpc1 可以将QM和机器人的触发事件全部转到 QF 引擎触发是通用的,TXT的所有触发转换成小写后在LUA中就可使用,如说明书中缺省可反馈至对接群…...
航展畅想:从F35机载软件研发来看汽车车载软件研发
两款经典战机的机载软件 F-22和F-35战斗机的研制分别始于1980年代和1990年代末,F-22项目在1981年启动,主要由洛克希德马丁(Lockheed Martin)和波音公司(Boeing)合作开发,以满足美军“先进战术战…...
用Dify搭建AI知识库
Dify 可以上传各种格式文档和抓取网页数据训练自已的知识库 一 安装 1 Docker安装 我基于Docker来安装的,所以本机先装Docker Desktop, Docker 安装方法在这里 2 Dify 安装 git clone https://github.com/langgenius/dify.git cd dify/docker copy .env.exampl…...
架构师:如何提高web网站的请求并发响应量?
文章目录 一、提出问题二、相关概念三、如何提高网站请求响应能力?四、负载均衡有那些方式?五、常用微服务架构图及推荐书籍 一、提出问题 今天,突然想到一个问题,双十一,那些电商网站的并发量是多大? 简…...
图论基础--孤岛系列
孤岛系列有: 孤岛总面积求解(用了dfs、bfs两种方法)和沉没孤岛(这里只写了dfs一种) 简单解释一下: 题目中孤岛的定义是与边缘没有任何接触的(也就是不和二维数组的最外圈连接)&…...
Docker学习—Docker的安装与使用
Docker安装 1.卸载旧版 首先如果系统中已经存在旧的Docker,则先卸载: yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2.配置Docker的yum库 首先…...
HC-SR04超声波传感器详解(STM32)
HC-SR04是一款广泛使用的超声波传感器,它通过发射和接收超声波来测量距离。本文将详细介绍HC-SR04的工作原理、引脚描述、STM32的接线方式以及如何通过STM32控制HC-SR04来测量距离。 一、HC-SR04传感器介绍 HC-SR04超声波传感器的主要参数如下: 工作电…...
如何在BSV区块链上实现可验证AI
发表时间:2024年10月2日 nChain的顶尖专家们已经找到并成功测试了一种方法:通过区块链技术来验证AI(人工智能)系统的输出结果。这种方法可以确保AI模型既按照规范运行,避免严重错误,遵守诸如公平、透明…...
Python快速安装软件包到环境的方案
问题描述 直接在终端输入,显示安装numpy包要20分钟, pip install numpyxxx.whl解决方案 直接搜索pip install 后在终端显示的.whl文件,在pypi.org官网下载, 之后在终端进入下载目录,从.whl文件安装软件包即可 pip …...
npm入门教程17:准备发布的npm包
一、环境准备 安装Node.js和npm: 确保你的计算机上已安装Node.js和npm。可以通过运行node -v和npm -v命令来检查它们的版本。如果没有安装,可以从Node.js官方网站下载并安装最新版本。 注册npm账号: 访问npm官网,点击“Sign Up”…...
协程1 --- 发展历史
文章目录 一个编译器问题背景解决 协程为什么一开始没发展成一等公民?自顶向下、逐步求精(Top-down, stepwise refinement)线程的出现 协程的雄起IO密集型同步语义实现异步发展史 线程和协程的关系并发性调度方式资源占用 一个编译器问题 协…...
VBA10-处理Excel的动态数据区域
end获取数据边界 1、基本语法 1-1、示例: 2、配合row和column使用 2-1、示例1 2-2、示例2 此时,不管这个有数值的区域,怎么增加边界,对应的统计数据也会跟着变的!...
【git】使用记录
一、安装 参考:Git2.45.2下载安装记录(windows 11)_win11安装git-CSDN博客...
代码随想录算法训练营第三十八天|Day38 动态规划
322. 零钱兑换 视频讲解:https://www.bilibili.com/video/BV14K411R7yv https://programmercarl.com/0322.%E9%9B%B6%E9%92%B1%E5%85%91%E6%8D%A2.html 思路 #define min(a, b) ((a) > (b) ? (b) : (a)) int coinChange(int* coins, int coinsSize, int amount…...
使用C++和libcurl库实现HTTP请求(GET、POST、文件上传)
在现代软件开发中,与外部API服务进行通信已成为常见需求。本文将展示如何使用C和libcurl库实现基本的HTTP请求,包括GET请求、POST请求(带JSON数据)以及包含文件上传的POST请求。 准备工作 首先,需要确保已安装libcur…...
makefile例子
$指代当前目标,就是Make命令当前构建的那个目标。比如,make foo的 $ 就指代foo。 $< 指代第一个前置条件。比如,规则为 t: p1 p2,那么$< 就指代p1。 $? 指代比目标更新的所有前置条件,之间以空格分隔。比如&a…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...
OPENCV图形计算面积、弧长API讲解(1)
一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API…...
二叉树-144.二叉树的前序遍历-力扣(LeetCode)
一、题目解析 对于递归方法的前序遍历十分简单,但对于一位合格的程序猿而言,需要掌握将递归转化为非递归的能力,毕竟递归调用的时候会调用大量的栈帧,存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧,而非…...
Electron简介(附电子书学习资料)
一、什么是Electron? Electron 是一个由 GitHub 开发的 开源框架,允许开发者使用 Web技术(HTML、CSS、JavaScript) 构建跨平台的桌面应用程序(Windows、macOS、Linux)。它将 Chromium浏览器内核 和 Node.j…...
