效果:

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