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 &…

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…

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

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

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

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

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

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

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

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

蓝牙在物联网中的应用,相比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;即对象嵌套属性发生了…

HarmonyOS首次尝试-HelloWorld

我的旧手机是个HUAWEI PCT-AL10 HarmonyOS 3.0.0(Android 10) 插上后&#xff0c;studio能显示连接上了手机设备&#xff0c;创建的demo使用的是API9&#xff0c;也就是当前的最新版本。 点击运行报错&#xff1a; 点击去往帮助页&#xff0c;做的也挺好&#xff0c;有直达的…

Redis第1讲——入门简介

Java并发编程的总结和学习算是告一段落了&#xff0c;这段时间思来想去&#xff0c;还是决定把Redis再巩固和学习一下。毕竟Redis不论是在面试还是实际应用中都是极其重要的&#xff0c;在面试中诸如Redis的缓存问题、热key、大key、过期策略、持久化机制等&#xff1b;还有在实…

最新UI酒桌喝酒游戏小程序源码,直接上传源码到开发者端即可,带流量主

源码介绍&#xff1a; 2023最新UI酒桌喝酒游戏小程序源码 娱乐小程序源码 带流量主.修改增加了广告位&#xff0c;直接上传源码到开发者端即可。 通过后改广告代码&#xff0c;然后关闭广告展示提交&#xff0c;通过后打开即可。无广告引流。 流量主版本的&#xff08;配合流…

深度解读 Cascades 查询优化器

数据库中查询优化器是数据库的核心组件&#xff0c;其决定着 SQL 查询的性能。Cascades 优化器是 Goetz 在 volcano optimizer generator 的基础上优化之后诞生的一个搜索框架。 本期技术贴将带大家了解 Cascades 查询优化器。首先介绍 SQL 查询优化器&#xff0c;接着分析查询…

CentOS 7 源码部署 Nginx

文章目录 1. 概述2. 部署示例2.1 下载和解压 Nginx 源码2.2 安装编译依赖包2.3 编译和安装2.4 启动 Nginx2.5 配置防火墙2.6 设置 Nginx 为系统服务2.7 配置访问 3. 扩展知识 1. 概述 Nginx 是一款高性能的开源 Web 服务器软件&#xff0c;广泛应用于互联网领域。本篇博客将介…

【日积月累】Spring中的AOP与IOC相关问题详解

Spring中的AOP与IOC 1.前言2.Spring AOP&#xff08;面向切面编程&#xff09;2.1 AOP的实现过程2.2 AOP代理模式的类型2.2.1JDK的动态代理2.2.2CGLIB的动态代理 2.3AOP应用常见场景2.3.1日志记录 2.4对AOP的理解 3.Spring IOC&#xff08;Inversion of Control&#xff0c;控…

29、Windows安全配置

文章目录 一、Windows安全配置简介二、账户策略2.1 密码策略2.2 账户锁定策略 三、本地策略3.1 用户权限分配 四、安全设置4.1 账户4.2 审核4.3 设备4.4交互式登录4.5 网络访问4.6 网络安全4.7 用户账户控制4.8 防火墙配置 五、高级审核策略设置5.1 账户登录5.2 账户管理5.3 对…

架构设计系列之基础:基础理论(一)

在软件开发和软件架构领域&#xff0c;深厚的理论基础是构建高质量、可维护、可扩展系统的关键&#xff0c;本部分内容将围绕这些基础理论展开。&#xff08;本部分内容介绍第一部分&#xff1a;编程三范式、架构设计原则、软件设计七原则&#xff09; 一、编程三范式 编程范…

112. 路径总和(Java)

目录 解法&#xff1a; 官方解法&#xff1a; 方法一&#xff1a;广度优先搜索 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 方法二&#xff1a;递归 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 给你二叉树的…

(C++)最大连续1的个数--滑动窗口

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

MIT18.06线性代数 笔记2

文章目录 正交向量与子空间子空间投影投影矩阵和最小二乘正交矩阵和Gram-Schmidt正交化行列式及其性质行列式公式和代数余子式克拉默法则、逆矩阵、体积特征值和特征向量对角化和A的幂微分方程和exp(At)马尔科夫矩阵 傅里叶级数复习二 正交向量与子空间 向量正交&#xff1a;x…