【QML】QML复制文件或文件夹,显示进度,多线程复制

1. 效果

  • 可以显示复制文件文件夹的进度
    在这里插入图片描述
  • 复制文件: bool copyFileFunc(QString _from, QString _to);
  • 复制文件夹:bool copyDirectoryFiles(const QString &_from, const QString &_to);
  • 举例:
	//复制文件copyhelper.copyFileToDir("./test.txt", "d:/copytest/dir/test1.txt");//复制文件夹copyhelper.copyFileToDir("./copyTest", "d:/copytest/dir/copyTest1");

2. QML代码

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4Window {width: 640height: 480visible: truetitle: qsTr("copy file")Rectangle{id: _progresswidth: parent.widthheight: parent.height / 2border.color: "blue"border.width: 1property string processv: "0"ProgressBar {id: pbarwidth: 480;height: 30minimumValue:  0maximumValue:  100value: 0anchors.centerIn: parentstyle: ProgressBarStyle{id: progressStylebackground: Rectangle{color: "lightgrey"radius: 6}progress: Rectangle{color: control.value === 100 ? "#b1d946" :"#4c7aff"radius: 6}panel: Item{//通过panel属性,可以加载  progress Text background等组件//设置外边框implicitWidth: 480;implicitHeight: 15;Loader{anchors.fill:  parent;sourceComponent: background;}Loader{id: progressLoader;anchors.top: parent.top;anchors.left: parent.left;anchors.bottom:  parent.bottom;anchors.margins: 0;z: 1;width: currentProgress * (parent.width);sourceComponent: progressStyle.progress;}Text{color: "black"text: _progress.processvz: 2anchors.centerIn: parent}}}}}Button{width: 200height: 100anchors.top: _progress.bottomanchors.horizontalCenter: _progress.horizontalCenteranchors.topMargin: 20text: qsTr("开始复制")onClicked: {console.log("开始复制")//复制文件//copyhelper.copyFileToDir("./test.txt", "d:/copytest/dir/test1.txt");//复制文件夹copyhelper.copyFileToDir("./copyTest", "d:/copytest/dir/copyTest1");}}Connections{target: copyhelperfunction onQmlCopyProgress(value){pbar.value = value;_progress.processv =  value + "%";}}
}

3. main.c代码

#include <QGuiApplication>
#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>
#include "copyhelper.h"int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQApplication app(argc, argv);QQmlApplicationEngine engine;engine.rootContext()->setContextProperty("copyhelper", new CopyHelper);const QUrl url(QStringLiteral("qrc:/main.qml"));QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection);engine.load(url);return app.exec();
}

4. .pro代码

QT += quick qml widgets core# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \copyfiles.cpp \copyhelper.cpp \main.cppRESOURCES += qml.qrc# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetHEADERS += \copyfiles.h \copyhelper.h

5. C++代码

  • 创建两个类 CopyHelperCopyFiles
  • CopyFiles中是具体实现
  • CopyHelper 为了实现多线程

5.1 copyfile.h

#ifndef COPYFILES_H
#define COPYFILES_H#include <QObject>
#include <QDebug>
#include <QFile>        //文件操作
#include <QDataStream>  //数据流
#include <QThread>      //线程class CopyFiles : public QObject
{Q_OBJECT
public://只能显式构造/***  QString _srcFilePath    : 源文件路径*  QString _dstPath        : 目标路径*  QObject *parent = 0     : 父对象指针,默认为空*/explicit CopyFiles(QString _srcFilePath, QString _dstPath,QObject *parent = 0);signals:void startCopyFile(QString, QString);   //复制文件信号void startCopyDir(QString, QString);    //复制文件夹信号void copyProcess(QString);              //复制文件进度信号public slots:/*** @brief copyFileFunction : 复制文件信号处理槽* @param _from : 源文件名* @param _to   : 目标文件名* @return bool : 返回类型 成功返回true 失败返回false*/bool copyFileFunc(QString _from, QString _to);/*** @brief copyDirectoryFiles : 复制文件夹* @param _from : 源文件夹路径* @param _to   : 目标文件夹路径* @return  : 成功返回true 失败返回false*/bool copyDirectoryFiles(const QString &_from, const QString &_to);private:bool m_firstRead = true;qint64 m_total = 0;qint64 m_now = 0;private:void getDirSize(QString _dir, qint64* size);bool copyFile(QString _from, QString _to, qint64* nowSize, qint64 totalSize);
};#endif // COPYFILES_H

5.2 copyfile.cpp

#include "copyfiles.h"
#include "qfileinfo.h"
#include <QFile>
#include <QDir>CopyFiles::CopyFiles(QString _srcFilePath, QString _dstPath, QObject *parent)
{qDebug() << QThread::currentThreadId() << _srcFilePath << _dstPath;
}bool CopyFiles::copyFileFunc(QString _from, QString _to)
{qint64 fileSize = 0;qint64 totalCopySize = 0;//文件夹创建QFileInfo fininfo(_to);QDir path;if(!path.exists(fininfo.absolutePath())){path.mkdir(fininfo.absolutePath());}//文件对象QFile tofile;tofile.setFileName(_to);QFile fromfile;fromfile.setFileName(_from);fileSize = fromfile.size();/* 复制文件 */return copyFile(_from, _to, &totalCopySize, fileSize);
}bool CopyFiles::copyDirectoryFiles(const QString &_from, const QString &_to)
{QDir sourceDir(_from);QDir targetDir(_to);qDebug() << "copy form" <<_from << _to;/* 如果目录不存在,则创建 */if(!targetDir.exists()){if(!targetDir.mkdir(targetDir.absolutePath())){return false;}}QFileInfoList fileInfoList = sourceDir.entryInfoList();if(m_firstRead){qDebug() << "copyDirectoryFiles count:" << fileInfoList.count();/* 获取文件夹总大小 */m_total = 0;getDirSize(_from, &m_total);/* 标志位 */m_now = 0;m_firstRead = false;qDebug() << "copyDirectoryFiles: " << m_total << m_now;/* 复制完成 */if(m_now == m_total){m_firstRead = true;}}foreach(QFileInfo fileInfo, fileInfoList){if(fileInfo.fileName() == "." || fileInfo.fileName() == ".."){continue;}/* 当前为目录递归进行copy */if(fileInfo.isDir()){if(!copyDirectoryFiles(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()))){return false;}}/* 复制文件 */else{if(!copyFile(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()), &m_now, m_total)){return false;}}}return true;
}void CopyFiles::getDirSize(QString _dir, qint64* size)
{QDir sourceDir(_dir);QFileInfoList fileInfoList = sourceDir.entryInfoList();/* 遍历文件夹 */foreach(QFileInfo fileInfo, fileInfoList){if(fileInfo.isFile()){if(fileInfo.fileName() != "." && fileInfo.fileName() != ".."){*size += fileInfo.size();qDebug() << "1-----" << fileInfo.fileName() << *size;}}else if(fileInfo.isDir()){/* 递归 */if(fileInfo.fileName() != "." && fileInfo.fileName() != ".."){getDirSize(fileInfo.filePath(), size);qDebug() << "2-----" << fileInfo.fileName() <<fileInfo.filePath();}}}
}bool CopyFiles::copyFile(QString _from, QString _to, qint64* nowSize, qint64 totalSize)
{qDebug() << "子线程ID:" << QThread::currentThreadId();char * byteTemp = new char[1024*8]; //每次复制8kqint64 fileSize = 0;qint64 totalCopySize = 0;//文件夹创建QFileInfo fininfo(_to);QDir path;if(!path.exists(fininfo.absolutePath())){path.mkdir(fininfo.absolutePath());}//文件对象QFile tofile;tofile.setFileName(_to);QFile fromfile;fromfile.setFileName(_from);//文件读取判断if(!tofile.open(QIODevice::WriteOnly)){qDebug() << "无法打开目标文件1";delete[](byteTemp);return false;}if(!fromfile.open(QIODevice::ReadOnly)){qDebug() << "无法打开目标文件2";delete[](byteTemp);return false;}//文件大小QDataStream out(&tofile);//文件流out.setVersion(QDataStream::Qt_4_0);fileSize = fromfile.size();QDataStream in(&fromfile);in.setVersion(QDataStream::Qt_4_0);qDebug() << "文件总大小:" << fileSize << " / " << QString::number(totalSize);//循环复制文件while(!in.atEnd()){qint64 readSize = 0;//每次读取8kreadSize = in.readRawData(byteTemp, 1024*8);    //读取复制文件到缓存并返回读取的实际大小out.writeRawData(byteTemp, readSize);           //写到输出流totalCopySize += readSize;                      //累计已复制大小*nowSize += readSize;int tmpVal = *nowSize / (double)totalSize * 100;//复制进度计算emit copyProcess(QString::number(tmpVal));      //发射当前复制进度//qDebug() << "now:" << *nowSize;}//复制完成if(totalCopySize == fileSize){tofile.setPermissions(QFile::ExeUser);//设置文件权限tofile.close();     //关闭文件流fromfile.close();   //关闭文件流delete[](byteTemp);return true;        //返回复制结果-成功}else{delete[](byteTemp);return false;       //返回复制结果-失败}
}

5.3 copyhelper.h

#ifndef COPYHELPER_H
#define COPYHELPER_H#include <QObject>class CopyHelper : public QObject
{Q_OBJECT
public:explicit CopyHelper(QObject *parent = 0);public:/*** @brief copyFileToDir 复制文件到目录* @return QString 返回字符串*/Q_INVOKABLE QString copyFileToDir(QString _from, QString _to);signals:/*** @brief qmlCopyProgress 供qml使用的复制文件进度信号* @param value*/void  qmlCopyProgress(QString value);private :/*** @brief testReadFile 测试读取文件*/void testReadFile();private slots:/*** @brief reciveCopyProgress 接收文件进度槽*/void reciveCopyProgress(QString);
};#endif // COPYHELPER_H

5.4 copyhelper.cpp

#include "copyhelper.h"
#include <QDebug>
#include <QFile>
#include <QDataStream>
#include <QThread>
#include <QFileInfo>
#include "copyfiles.h"CopyHelper::CopyHelper(QObject *parent) : QObject(parent)
{qDebug() << "文件复制助手线程ID:" <<QThread::currentThreadId();
}//复制文件到目录
QString CopyHelper::copyFileToDir(QString _from, QString _to)
{//构造复制文件类CopyFiles * m_pCopyFile = new CopyFiles(_from, _to);//复制文件子线程QThread * m_pCopyFilethread =  new QThread();m_pCopyFile->moveToThread(m_pCopyFilethread); //子线程中执行文件复制//连接文件复制信号connect(m_pCopyFile,SIGNAL(startCopyFile(QString,QString)),m_pCopyFile,SLOT(copyFileFunc(QString,QString)));connect(m_pCopyFile,SIGNAL(startCopyDir(QString,QString)),m_pCopyFile,SLOT(copyDirectoryFiles(QString,QString)));connect(m_pCopyFile,SIGNAL(copyProcess(QString)),this,SLOT(reciveCopyProgress(QString)));//链接线程完成信号connect(m_pCopyFilethread, SIGNAL(finished()), m_pCopyFilethread, SLOT(deleteLater()));connect(m_pCopyFilethread, &QThread::finished, m_pCopyFilethread, &QObject::deleteLater);//启动复制线程m_pCopyFilethread->start();//判断文件还是文件夹QFileInfo fileInfo(_from);if(fileInfo.isDir()){//发射文件夹复制开始信号emit m_pCopyFile->startCopyDir(_from, _to);}else{//发射文件复制开始信号emit m_pCopyFile->startCopyFile(_from, _to);}return "复制成功";
}//测试读取文件
void CopyHelper::testReadFile()
{//测试复制文件QString strFileName = "d:/test.rar";if (!QFile::exists(strFileName)){return;} //文件不存在QFile file(strFileName);if (!file.open(QFile::ReadOnly)){return;}//文件无法打开QDataStream in(&file);      //数据流int nFileSize = file.size();//文件大小int p = 0;                  //当前复制位置while (!in.atEnd()) {char buffer [8192];int readsize = 0;readsize = in.readRawData(buffer,8192);p = file.pos();qDebug() <<"文件总大小:"<<nFileSize<<"读取大小"<<readsize<<" 当前复制进度"<<QString::number(p);}
}//接收文件进度
void CopyHelper::reciveCopyProgress(QString value)
{emit qmlCopyProgress(value);//发射接收文件进度
}

6. 参考

  • QML复制文件并显示进度
  • Qt制作有进度条的拷贝文件夹和文件的小Demo

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

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

相关文章

推荐12款好用的在线平面设计工具,让设计更简单

平面设计是图形表达和信息展示的重要手段&#xff0c;在游戏场景和角色造型、插画、广告制作等艺术设计领域有着重要的应用&#xff0c;如海报设计、包装设计等。 平面设计强调视觉传达&#xff0c;一般以图像、图形和文字等视觉元素为主要手段&#xff0c;通过排版、配色、构…

SpringBoot、Java AOP实现方式

SpringBoot、Java AOP实现方式 搭建项目环境 我这里直接使用Maven创建项目之后再pom.xml中导入包 Spring版本 如果你的版本有最新的&#xff0c;最简单的办法就是&#xff0c;将版本都换成统一的&#xff0c;因为发布时候都是每个版本统一发布的&#xff0c;如果出现不兼容的…

大模型讲座

盘古NLP大模型典型场景 千亿大模型训练难点和解决方案 训练状态不稳定&#xff08;经常训练中断等&#xff09; 解决1&#xff1a;对loss和梯度等多维状态实时监测。对数据、学习率、参数精度、模型梯度进行针对性调整和断点恢复。 调整学习率的代码如下。调整参数、梯度类似…

kali安装HTTrack报错Unable to locate package httrack

kali安装后&#xff0c;直接安装Httrack导致报错 Unable to locate package httrack &#xff08;这里因为解决了&#xff0c;无法重现&#xff0c;则使用错误的包httrackttttt&#xff09; 原因&#xff1a;安装kali后第一次使用系统&#xff0c;则应该运行update命令 sudo …

基于ssm省出口基地公共信息服务平台论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本n省出口基地公共信息服务平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞…

算法训练营Day19

#Java #二叉树 #双指针 开源学习资料 Feeling and experiences&#xff1a; 二叉搜索树的最小绝对差&#xff1a;力扣题目链接 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的…

eNSP小实验--实现全网互通

目录 一、建立以下拓扑图&#xff0c;并实现全网互通 二、分析 1、接入层交换机SW4、SW5划分vlan 2、汇聚层交换机SW2,SW3配置ip作为vlan网关&#xff0c;与SW1直连 3、核心交换机SW1配置ip 与汇聚层交换机和R1直连 4、SW1,SW2,SW3,R1配置静态路由&#xff0c;使得vlan10,…

算法学习——回溯算法

回溯算法 理论基础回溯法的效率回溯法解决的问题回溯法模板 组合思路回溯法三部曲 代码 组合&#xff08;优化&#xff09;组合总和III思路代码 电话号码的字母组合思路回溯法来解决n个for循环的问题回溯三部曲代码 组合总和思路代码 组合总和II思路代码 理论基础 什么是回溯法…

教师职业规划

教师是一份充满责任和使命感的职业&#xff0c;也是一个具有广泛影响力的职业。作为一名教师&#xff0c;不仅要传授知识&#xff0c;更要培养学生的品德和能力&#xff0c;为他们的未来发展奠定基础。因此&#xff0c;进行职业规划对于教师来说是非常重要的。 首先&#xff0…

VUE篇之可拖动裁剪框

涉及知识点&#xff1a; offsetLeft, offsetTop, offsetWidth, offsetHeight&#xff1b;offsetX, offsetY&#xff1b;clientX&#xff0c;clientY css:clip-path 学习直通车&#xff1a;HTMLElement.offsetLeft - Web API 接口参考 | MDN MouseEvent.offsetX - Web API 接…

利用原始套接字解决mac地址错误问题【南瑞SysKeeper-2000】

一&#xff1a;案例描述 一键可视顺控图像智能项目在网络部署过程中&#xff0c;对网络限制隔离安全性要求很高&#xff0c;用到正向隔离装置&#xff08;南瑞SysKeeper-2000型号&#xff09;。 图一 正向装置示意图 现场发现问题&#xff1a;直连网线情况下&#xff0c;我方…

德人合科技 | 公司电脑文件加密系统

公司电脑文件加密系统是一种可以对电脑文件进行加密的保护机制。它使用驱动层透明加密技术&#xff0c;能够在用户无感知的情况下对文件进行加密&#xff0c;从源头上保障数据安全和使用安全。 PC端访问地址&#xff1a; www.drhchina.com 此类系统主要有以下几个特点和功能&a…

Web前端-JavaScript(js循环)

1.循环 1.1 for循环 语法结构 for(初始化变量; 条件表达式; 操作表达式 ){//循环体 }名称作用初始化变量通常被用于初始化一个计数器&#xff0c;该表达式可以使用 var 关键字声明新的变量&#xff0c;这个变量帮我们来记录次数。条件表达式用于确定每一次循环是否能被执行。…

Git账户密码http方式的配置

Git账户密码http方式的配置 入门 git在提交时每次都需要输入密码和账号信息&#xff0c;可以将账号和密码进行持久化存储&#xff0c; 当git push的时候输入一次用户名和密码就会被记录&#xff0c; 不需要每次输入&#xff0c;提高效率&#xff0c;进行一下配置&#xff1…

深入学习《大学计算机》系列之第1章 1.4节——从二进制起源窥见的奥秘

一.欢迎来到我的酒馆 第1章 1.4节&#xff0c;从二进制起源窥见的奥秘。 目录 一.欢迎来到我的酒馆二.二进制的起源1.关于莱布尼茨2.莱布尼茨和牛顿的恩怨情仇 二.二进制的起源 本节内容属于知识拓展&#xff0c;通过讲解几个小故事&#xff0c;向大家介绍二进制的起源。 1.关…

基于低代码的文档管理系统:实现高效协作与控制

在企业和组织中&#xff0c;文档管理是一项至关重要的任务。文档包括各种类型的信息&#xff0c;如合同、报告、会议记录、产品规格等&#xff0c;它们都需要被妥善保管并确保随时可供查阅。 传统的文档管理方法往往效率低下&#xff0c;且容易出错。随着技术的发展&#xff0…

亚信安慧AntDB数据库引领大数据新纪元,星河案例彰显卓越表现

亚信科技及其附属公司亚信安慧在第六届大数据“星河”案例评选中&#xff0c;凭借其卓越的数据库技术实力&#xff0c;再次站在了行业的聚光灯下。这次的显著成果不仅是对亚信科技技术能力的肯定&#xff0c;更是对其在数据库领域持续创新和领先地位的认可。 图&#xff1a;亚信…

3D小球跑酷

目录 一、前言 二、开发环境 三、场景搭建 1. 创建项目 2. 创建场景内物体 2.1 创建跑道 2.2 创建玩家 2.3 创建障碍物 2.4 改变跑道和障碍物的颜色 2.4.1 创建材质 2.4.2 给跑道和障碍物更换材质 四、功能脚本实现 1. 创建玩家脚本 2. 相机跟随 3. 胜负的判定 3…

单光子如何“玩转”单原子?| 量子简史

在量子力学诞生约100年后的今天&#xff0c;物理学家仍在不断了解光与物质之间的相互作用。 上世纪初&#xff0c;量子力学发展的驱动力之一是人们需要了解为什么原子只能发出特定波长的光。不久之后&#xff0c;量子力学被应用于分子&#xff0c;然后是固体。从另一个方向来看…

Springboot数据加密篇

一、密码加密 1.1Hash算法(MD5/SHA-512等) 哈希算法&#xff0c;又称摘要算法&#xff08;Digest&#xff09;&#xff0c;是一种将任意长度的输入通过散列函数变换成固定长度的输出的单向密码体制。这种映射的规则就是哈希算法&#xff0c;而通过原始数据映射之后得到的二进制…