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.4
Window {
width: 640
height: 480
visible: true
title: qsTr ( "copy file" )
Rectangle{
id: _progress
width: parent. width
height: parent. height / 2
border. color: "blue"
border. width: 1
property string processv: "0"
ProgressBar {
id: pbar
width: 480 ;
height: 30
minimumValue: 0
maximumValue: 100
value: 0
anchors. centerIn: parent
style: ProgressBarStyle{
id: progressStyle
background: Rectangle{
color: "lightgrey"
radius: 6
}
progress: Rectangle{
color: control. value == = 100 ? "#b1d946" : "#4c7aff"
radius: 6
}
panel: Item{
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. processv
z: 2
anchors. centerIn: parent
}
}
}
}
}
Button{
width: 200
height: 100
anchors. top: _progress. bottom
anchors. horizontalCenter: _progress. horizontalCenter
anchors. topMargin: 20
text: qsTr ( "开始复制" )
onClicked: {
console. log ( "开始复制" )
copyhelper. copyFileToDir ( "./copyTest" , "d:/copytest/dir/copyTest1" ) ;
}
}
Connections{
target: copyhelper
function 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) ;
# endif
QApplication 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 .0
SOURCES += \
copyfiles. cpp \
copyhelper. cpp \
main. cpp
RESOURCES += 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 += target
HEADERS += \
copyfiles. h \
copyhelper. h
5. C++代码
创建两个类 CopyHelper
和 CopyFiles
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:
explicit CopyFiles ( QString _srcFilePath, QString _dstPath, QObject * parent = 0 ) ;
signals:
void startCopyFile ( QString, QString) ;
void startCopyDir ( QString, QString) ;
void copyProcess ( QString) ;
public slots:
bool copyFileFunc ( QString _from, QString _to) ;
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
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 ;
}
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 ] ;
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) ;
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 ;
readSize = in. readRawData ( byteTemp, 1024 * 8 ) ;
out. writeRawData ( byteTemp, readSize) ;
totalCopySize += readSize;
* nowSize += readSize;
int tmpVal = * nowSize / ( double ) totalSize * 100 ;
emit copyProcess ( QString:: number ( tmpVal) ) ;
}
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:
Q_INVOKABLE QString copyFileToDir ( QString _from, QString _to) ;
signals:
void qmlCopyProgress ( QString value) ;
private :
void testReadFile ( ) ;
private slots:
void reciveCopyProgress ( QString) ;
} ;
# endif
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