Qt 线程

💡 进度条显示拷贝进度(verson 1)

窗口上放置一个按钮和一个进度条部件,点击按钮,进行拷贝操作 —— 打开对话框选择源文件,然后再打开一个对话框 选择 目标文件存放位置和名称。拷贝过程中进度条显示当前进度(大文件)。不允许用QFile 的 copy 方法 —— 把源文件分解开,然后一帧一帧写入目标文件。
在这里插入图片描述

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QtWidgets>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_pushButton_released();private:Ui::Widget *ui;
};#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"#define KB 1024Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);ui->progressBar->setValue(0);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_released()
{// 1.选定源文件QString srcName = QFileDialog::getOpenFileName(this, tr("选择文件"), \"D:/Packages_", tr("all  (*.*)"));if (srcName.isEmpty())return ;qDebug() << "src: " << srcName;// 2.选定目标文件QString destName = QFileDialog::getSaveFileName(this, tr("保存文件"), \"e:", tr("all  (*.*)"));if (destName.isEmpty())return ;qDebug() << "dest: " << destName;QFile srcFile(srcName);if (!srcFile.open(QIODevice::ReadOnly)){qDebug() << "打开文件失败";return ;}QFile destFile(destName);if (!destFile.open(QIODevice::ReadWrite | QIODevice::Truncate)){qDebug() << "复制文件失败";return ;}ui->progressBar->setValue(0);			// 确保每次点击按钮时,进度条都是从 0 开始qint64 totalSize = srcFile.size();qint64 currentSize = 0;QByteArray buffer;// 3.开始拷贝--不断读取,然后写入while (!srcFile.atEnd()){buffer.clear();buffer = srcFile.read(KB);destFile.write(buffer);// 4.更新进度值currentSize += buffer.size();ui->progressBar->setValue(100 * currentSize / totalSize);}
}

运行结果如下:(复制文件时,拖动窗口会产生卡顿)
在这里插入图片描述

QT 线程

GUI 线程(QT 的主线程)

QT 的主线程称为 GUI 线程,负责初始化界面监听事件循环,并根据事件处理做出界面上的反馈。

使用多线程的好处

1、提高应用界面的响应速度;

这对于开发图形界面程序尤其重要,当一个操作耗时很长时(比如大批量 I/O 或大量矩阵变换等CPU密集操作),整个系统都会等待这个操作,程序就不能响应键盘、鼠标、菜单等操作,而使用多线程技术可将耗时长的操作置于一个新的线程,从而不会影响到 主 GUI 线程,从而避免上述问题。

2、使多核心 CPU 系统更加有效;

当线程数不大于CPU核数时,操作系统可以调度不同的线程运行于不同的CPU核上。

3、改善程序结构;

一个既长又复杂的进程可以考虑分为多个线程,成为独立或半独立的运行部分,这样有利于程序的理解和维护。

创建一个界面,界面 show 以后调用睡眠函数,观察效果。
在这里插入图片描述

QThread 类

相关接口

Public Functions:QThread(QObject *parent = 0); 			// 构造函数  // pthread_createbool 	isFinished() const;  			// 判断线程是否退出bool	wait(unsigned long time = ULONG_MAX);   // pthread_join(&id)// 等待某个线程结束,最多等待time ms,如果时间没有设置,那么永远等待。Public Slots:void	start(Priority priority = InheritPriority)  // 启动线程必须使用startvoid	terminate();				// 杀死线程  	// pthread_cancelStatic Public Members:Qt::HANDLE	currentThreadId() [static] 		// 得到当前执行者线程ID,可以直接qDebugvoid	sleep(unsigned long secs) [static]void	msleep(unsigned long msecs) [static]void	usleep(unsigned long usecs) [static]睡眠函数不能在主线程调用,会造成界面卡死。Protected Functions:	virtual void run();  	// 启动新线程不能直接调用run,需要调用 start 接口,// start 会启动新线程,然后执行run里的代码块。

编程流程

1)子类化 QThread(重写一个类,继承自 QThread);
2)重写 run 函数,执行耗时操作(run 函数内有一个 while / for 循环 或 sleep);
3)子线程类实现 公共方法,供主线程传参(主线程给子线程传参);
4)主线程内 定义并实例化子线程的类对象;
5)主线程调用 start 方法 启动子线程;
6)设置必要的 信号和槽 做连接 ——> 子线程给主线程传参;
7)设置一个标记 来控制循环的退出,或者父线程调用 terminate 停止子线程。
注意:子线程内不允许操作界面上的任何部件,所有界面操作都应该由 GUI 主线程来进行

💡 练习

重写一个线程子类,GUI 线程传递一个值给子线程。界面放置一个按钮,点击按钮后线程开始运行。子线程打印主线程传递的值以后睡眠任意时间,线程运行结束后通知主线程自己运行的时间,主线程把子线程睡眠的总时间显示到界面上。
在这里插入图片描述

mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>
#include <qdebug.h>class MyThread : public QThread					// 1)重写一个类,继承自 QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = 0);void setValue(int num) {this->val = num;}	// 3)子线程类实现 公共方法,供主线程传参signals:void valueSignal(int);						// 6)子线程发信号给主线程public slots:private:void run();									// 2)重写 run 函数int val;
};#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"MyThread::MyThread(QObject *parent) :QThread(parent)
{
}void MyThread::run()					// 2)重写 run 函数
{qDebug() << "From parent thread: val = " << val;QThread::sleep(16);					// 2)run 函数内有一个 while/for 循环 或 sleepemit valueSignal(16);
}
widget.h
#define WIDGET_H#include <QtWidgets>
#include "mythread.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private:Ui::Widget *ui;MyThread *myth;							// 4)主线程内 定义子线程的类对象public slots:void valueSlot(int);					// 6)主线程的槽接收来自子线程的信号private slots:void on_pushButton_clicked();
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);// 4)主线程内 实例化子线程的类对象myth = new MyThread(this);          // 使用 this 的目的仅是方便回收myth->setValue(98);					// 4.5)主线程传参给子线程// 6)设置必要的 信号和槽 做连接QObject::connect(myth, SIGNAL(valueSignal(int)), this,  SLOT(valueSlot(int)));
}Widget::~Widget()
{delete ui;
}void Widget::valueSlot(int num)			// 6)子线程给主线程传参的方式;信号与槽
{ui->label->setText("From child thread: val = " + QString::number(num));
}void Widget::on_pushButton_clicked()
{myth->start();						// 5)主线程调用 start 方法 启动子线程
}

实现效果如下:
在这里插入图片描述

💡 进度条显示拷贝进度(verson 2)

newthread.h
#ifndef NEWTHREAD_H
#define NEWTHREAD_H#include <QThread>
#include <QtWidgets>class NewThread : public QThread
{Q_OBJECT
public:explicit NewThread(QObject *parent = 0);void setFileNames(QString src, QString dest){srcName = src;destName = dest;}signals:void valueSignal(int);public slots:protected:void run();QString srcName;QString destName;int percentage;
};#endif // NEWTHREAD_H
newthread.cpp
#include "newthread.h"#define KB 1024NewThread::NewThread(QObject *parent) :QThread(parent)
{
}void NewThread::run()
{QFile srcFile(srcName);if (!srcFile.open(QIODevice::ReadOnly)){qDebug() << "打开文件失败";return ;}QFile destFile(destName);if (!destFile.open(QIODevice::ReadWrite | QIODevice::Truncate)){qDebug() << "复制文件失败";return ;}qint64 totalSize = srcFile.size();qint64 currentSize = 0;QByteArray buffer;while (!srcFile.atEnd()){buffer.clear();buffer = srcFile.read(KB);destFile.write(buffer);currentSize += buffer.size();percentage = 100 * currentSize / totalSize;emit valueSignal(percentage);}
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QtWidgets>
#include "newthread.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_pushButton_released();private:Ui::Widget *ui;NewThread *thr;public slots:void valueSlot(int);
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);ui->progressBar->setValue(0);thr = new NewThread(this);QObject::connect(thr, SIGNAL(valueSignal(int)), this,  SLOT(valueSlot(int)));
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_released()
{QString srcName = QFileDialog::getOpenFileName(this, tr("选择文件"), \"D:/Packages_", tr("all  (*.*)"));if (srcName.isEmpty())return ;qDebug() << "src: " << srcName;QString destName = QFileDialog::getSaveFileName(this, tr("保存文件"), \"e:", tr("all  (*.*)"));if (destName.isEmpty())return ;qDebug() << "dest: " << destName;ui->progressBar->setValue(0);				// 每次启动线程前,将进度条的进度 置0thr->setFileNames(srcName, destName);thr->start();								// 不要忘记启动线程
}void Widget::valueSlot(int value)
{ui->progressBar->setValue(value);
}

运行结果如下:(复制文件时,拖动窗口不会产生卡顿)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十三、YARN资源分配调用

1、为什么要先学习YARN组件&#xff1f; 在Hadoop文件系统中&#xff0c;YARN作为Hadoop系统的第三大组件&#xff0c;其中&#xff0c;第二大组件MapReduce组件是基于YARN运行的&#xff0c;即没有YARN无法运行MapReduce程序&#xff0c;所以需要同时学习YARN。 2、YARN &…

使用elasticsearch-dump工具备份ES数据库

ES数据库版本 elasticsearch7.16.0 备份工具 elasticsearch-dump &#xff08;docker 版&#xff09; 如果需要设置定时任务&#xff0c;需要使用使用elasticsearch-dump编译的二进制文件&#xff0c;需要nodejs、npm环境。 Docker 安装 docker pull elasticdump/elastics…

Day58力扣打卡

打卡记录 下一个更大元素 IV&#xff08;单调栈 x2&#xff09; 链接 class Solution:def secondGreaterElement(self, nums: List[int]) -> List[int]:ans [-1] * len(nums)s []t []for i, x in enumerate(nums):while t and nums[t[-1]] < x:ans[t.pop()] x # t…

Fabric建链docker-compose方式(客户端与节点主机分离+Fabric CA server容器化)

目录 一、客户端准备1.1、准备链目录和配置文件1.2、设置环境变量1.3、启动fabric-ca-server1.4、登记ca的admin用户 二、准备组织org12.1、准备组织目录2.2、生成组织org1的msp配置 三、准备peer0节点3.1、注册peer03.2、注册peer组织org1的user3.3、注册peer组织org1的admin3…

『npm』一条命令快速配置npm淘宝国内镜像

&#x1f4e3;读完这篇文章里你能收获到 一条命令快速切换至淘宝镜像恢复官方镜像 文章目录 一、设置淘宝镜像源二、恢复官方镜像源三、查看当前使用的镜像 一、设置淘宝镜像源 npm config set registry https://registry.npm.taobao.org服务器建议全局设置 sudo npm config…

Visuial Studio 打开 Unity 脚本时,脚本继承MonoBehaviour暂时失效为白色的解决方法

问题描述&#xff1a; u3d2020.3.47f1c1 vs2019 之前C#脚本A好好的&#xff0c;今天改了一行代码&#xff0c;在储存&#xff0c;就出现这个问题了&#xff0c;变白之后&#xff0c;新增的一行代码不生效&#xff0c;之前的代码照常运行。 如下办法都不能解决我的问题&…

科技提升安全,基于YOLOv6开发构建商超扶梯场景下行人安全行为姿态检测识别系统

在商超等人流量较为密集的场景下经常会报道出现一些行人在扶梯上摔倒、受伤等问题&#xff0c;随着AI技术的快速发展与不断普及&#xff0c;越来越多的商超、地铁等场景开始加装专用的安全检测预警系统&#xff0c;核心工作原理即使AI模型与摄像头图像视频流的实时计算&#xf…

没有明确的报错信息,阿里云国际版Windows服务器无法远程连接

在远程连接失败时&#xff0c;如果您没有收到系统返回的报错信息&#xff0c;并且ECS实例是运行中的状态&#xff0c;然后再根据以下步骤进行排查&#xff1a; 步骤一&#xff1a;使用阿里云Workbench工具测试远程登录 步骤二&#xff1a;检查是否有收到黑洞通知 步骤三&…

ekho环境Linux通过Docker安装

第一步 下载ekho-master源码 https://github.com/hgneng/ekho/archive/master.zip 第二步 创建DockerFile # 使用Ubuntu作为基础镜像 FROM ubuntu:latest# 更新Ubuntu的软件包列表 RUN apt-get updateRUN apt-get install -y apt-utils RUN apt-get install -y wget RUN …

多维时序 | MATLAB实现BWO-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现BWO-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现BWO-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现BWO-CNN-B…

C++ 日期 时间

C 标准库没有提供所谓的日期类型。C 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构&#xff0c;需要在 C 程序中引用 头文件。 有四个与时间相关的类型&#xff1a;clock_t、time_t、size_t 和 tm。类型 clock_t、size_t 和 time_t 能够把…

ElasticSearch之cat thread pool API

命令样例如下&#xff1a; curl -X GET "https://localhost:9200/_cat/thread_pool?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; node_name name …

Linux od命令教程:如何以各种格式转储文件(附案例详解和注意事项)

Linux od命令介绍 od命令在Linux中的全称是"octal dump"&#xff0c;它被用来以八进制和其他格式&#xff08;包括十六进制、十进制和ASCII&#xff09;转储文件。这个命令在你需要查看通常不易读的文件时非常有用&#xff0c;比如已经编译过的二进制文件。 Linux …

蓝牙在物联网中的应用,相比WIFI和NFC的优势?

蓝牙在物联网中有着广泛的应用&#xff0c;主要包括以下几个方面&#xff1a; 1、智能家居&#xff1a;蓝牙Mesh技术可以用于智能家居设备之间的连接和通信&#xff0c;实现设备的远程控制和管理。例如&#xff0c;通过蓝牙技术可以将智能音箱、智能电视、智能家电等设备连接起…

算法:多数元素(排序和Boyer Moore投票算法)

排序 时间复杂度 O(nlog⁡n) 空间复杂度 O(log⁡n) /*** param {number[]} nums* return {number}*/ var majorityElement function (nums) {nums nums.sort()// 排序之后数组中间的数一定是众数&#xff08;因为题目说数组中的众数大于 ⌊nums.length/2⌋&#xff09;retur…

Vue3-03-reactive() 响应式基本使用

reactive() 的简介 reactive() 是vue3 中进行响应式状态声明的另一种方式&#xff1b; 但是&#xff0c;它只能声明 【对象类型】的响应式变量&#xff0c;【不支持声明基本数据类型】。reactive() 与 ref() 一样&#xff0c;都是深度响应式的&#xff0c;即对象嵌套属性发生了…

flutter ‘Gradle Libs‘ was added by build file ‘app/build.gradle‘

相关问题解释文章 How to prefer settings.gradle repositories over build.gradle repositoriesMode 解释 问题描述 此问题是&#xff0c;直接创建的flutter项目&#xff0c;需要配置其他的maven仓库地址&#xff0c;和第三方module&#xff0c;结果始终都是无法成功 错误…

树莓派新手装机指南

如果你决定买一个树莓派&#xff0c;那么你一定已经了解过&#xff0c;不需要再做多余的介绍&#xff0c;由于之前就玩过树莓派&#xff0c;还是想弄一个属于自己的树莓派&#xff0c;因为它就像一个微型电脑&#xff0c;耗电非常低&#xff0c;我可以在家里24小时开机&#xf…

【Apache Pinot】Data upload jobtype 粗略分析

背景 目前我司大部分实时数据和离线数据都存储在 pinot 数据库中&#xff0c;离线数据需要通过脚本去生成对应的数据上传到数据库里面&#xff0c;但是其中 config 中有个 jobtype 让人有点迷惑&#xff0c;本文简单的做一个概念的整理 用处 先说一下流程&#xff0c;目前我…

数据结构总结(栈 队列)

概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系&#xff0c;并对这种结构定义相应的运算&#xff0c;而且确保经过这些运算后所得到的新结构仍然是原来的结构类型。 1.数据&#xff1a;所有能被输入到计算机中&#xff0c;且能被计算机处理的符号的集合。…