效果:

qml源码:
import QtQml 2.12
import QtQuick 2.12
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4
ApplicationWindow {
id:rootwindow
visible: true
width: 640
height: 480
title: qsTr("QML复制文件并显示进度")
property string processv: ""
Rectangle {
id: rgProgress
width: 500
height: 20
color: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 300
// 进度条
ProgressBar {
id: pbar
width: 480;
height: 15
minimumValue: 0
maximumValue: 100
value: 0
style: ProgressBarStyle{
id: progressStyle;
background: 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: "white";
text:(processv);
z: 2;
anchors.centerIn: parent;
}
}
}
}
}
Button
{
width: 200
height: 80
anchors.bottom: parent.bottom
anchors.bottomMargin: 100
anchors.horizontalCenter: parent.horizontalCenter
text: "选择文件"
onClicked:
{
fileDialog.visible = true ;
}
}
FileDialog {
id: fileDialog
title: "请选择一个文件"
folder: shortcuts.desktop
nameFilters : [ "视频 (*.mp4 *.avi *.ts *3gp *.wmv)", "全部 (*)" ]
selectMultiple:true
onAccepted: {
var filepath = fileDialog.fileUrl;
copyhelper.copyFileToDir(filepath.toString());
}
onRejected: {
console.log("取消选择")
}
Component.onCompleted: visible = false;
}
Connections
{
target: copyhelper
onQmlCopyProgress:
{
pbar.value = value;
processv = value + "%";
}
}
}
main.cpp源码:
#include <QApplication>
#include <QtQml>
#include <QQmlApplicationEngine>
#include "copyhelper.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("copyhelper", new CopyHelper);//注册复制文件类
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
复制文件类头文件:
#ifndef COPYFILES_H
#define COPYFILES_H
//头文件包含
#include <QObject>
#include <QDebug>
#include <QFile> //文件操作
#include <QDataStream> //数据流
#include <QThread> //线程
//继承QObject供QML使用
/**
* @brief 文件复制类
*/
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 starCopy(QString,QString);//复制文件信号
void copyProcess(QString); //复制文件进度信号
public slots:
/**
* @brief copyFileFunction : 复制文件信号处理槽
* @param _from : 源文件名
* @param _to : 目标文件名
* @return bool : 返回类型 成功返回true 失败返回false
*/
bool copyFileFunc( QString _from, QString _to);//槽
};
#endif // COPYFILES_H
复制文件类源文件:
#include "copyfiles.h"
CopyFiles::CopyFiles(QString Sourecfilepath,QString TargetPath,QObject *parent) : QObject(parent)
{
qDebug() << QThread::currentThreadId() << Sourecfilepath << TargetPath;
}
bool CopyFiles::copyFileFunc( QString _from, QString _to)
{
qDebug() << "子线程ID:" <<QThread::currentThreadId();
char* byteTemp = new char[8192];//每次复制8k
qint64 fileSize = 0;
qint64 totalCopySize = 0;
//文件对象
QFile tofile;
tofile.setFileName(_to);
QFile fromfile;
fromfile.setFileName(_from);
//文件读取判断
if(!tofile.open(QIODevice::WriteOnly))
{
qDebug() << "无法打开目标文件";
return false;
}
if(!fromfile.open(QIODevice::ReadOnly)){
qDebug() << "无法打开目标文件";
return false;
}
//文件大小
QDataStream out(&tofile);//文件流
out.setVersion(QDataStream::Qt_4_0);
fileSize = fromfile.size();
QDataStream in(&fromfile);
in.setVersion(QDataStream::Qt_4_0);
qDebug()<<"文件总大小:"<<QString::number(fileSize);
//循环复制文件
while(!in.atEnd())
{
qint64 readSize = 0;
//每次读取8k
readSize = in.readRawData(byteTemp, 8192);//读取复制文件到缓存并返回读取的实际大小
out.writeRawData(byteTemp, readSize);//写到输出流
totalCopySize += readSize;//累计已复制大小
int tmpVal = totalCopySize / (double)fileSize * 100;//复制进度计算
emit copyProcess(QString::number(tmpVal));//发射当前复制进度
}
//复制完成
if(totalCopySize == fileSize){
tofile.setPermissions(QFile::ExeUser);//设置文件权限
tofile.close();//关闭文件流
fromfile.close();//关闭文件流
return true;//返回复制结果-成功
}
else
return false;//返回复制结果-失败
}
#ifndef COPYHELPER_H
#define COPYHELPER_H
//头文件包含
#include <QObject>
//继承QObject供QML使用
/**
* @brief 文件复制助手类
*/
class CopyHelper : public QObject
{
Q_OBJECT
public:
//只能显式构造
/**
* @brief CopyHelper :构造函数
* @param parent
*/
explicit CopyHelper(QObject *parent = 0);
public:
/**
* @brief copyFileToDir 复制文件到目录
* @return QString 返回字符串
*/
Q_INVOKABLE QString copyFileToDir(QString);
signals:
/**
* @brief qmlCopyProgress 供qml使用的复制文件进度信号
* @param value
*/
void qmlCopyProgress(QString value);
public slots:
private :
/**
* @brief testReadFile 测试读取文件
*/
void testReadFile();
private slots:
/**
* @brief reciveCopyProgress 接收文件进度槽
*/
void reciveCopyProgress(QString);
};
#endif // COPYHELPER_H
#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 _filePath)
{
QString absolutePath = _filePath.remove(0,8);//文件绝对路径
qDebug()<< "文件绝对路径:" << absolutePath;
QFileInfo fininfo(absolutePath);//文件信息
QString dstPath = "d:/"+fininfo.fileName();
CopyFiles * m_pCopyFile = new CopyFiles(_filePath,dstPath);//构造复制文件类
QThread * m_pCopyFilethread = new QThread();//复制文件子线程
m_pCopyFile->moveToThread(m_pCopyFilethread); //子线程中执行文件复制
//连接文件复制信号
connect(m_pCopyFile,SIGNAL(starCopy(QString,QString)),m_pCopyFile,SLOT(copyFileFunc(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();
//发射文件复制开始信号
emit m_pCopyFile->starCopy(absolutePath,dstPath);
return "复制成功";
}
//测试读取文件
void CopyHelper::testReadFile()
{
QString strFileName ="c:/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);//发射接收文件进度
}
TEMPLATE = app
QT += qml quick widgets core
CONFIG += c++11
SOURCES += main.cpp \
copyhelper.cpp \
copyfiles.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
HEADERS += \
copyhelper.h \
copyfiles.h