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: truetitle: qsTr ( "copy file" ) Rectangle{ id: _progresswidth: parent. widthheight: parent. height / 2 border. color: "blue" border. width: 1 property string processv: "0" ProgressBar { id: pbarwidth: 480 ; height: 30 minimumValue: 0 maximumValue: 100 value: 0 anchors. centerIn: parentstyle: ProgressBarStyle{ id: progressStylebackground: 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. processvz: 2 anchors. centerIn: parent} } } } } Button{ width: 200 height: 100 anchors. top: _progress. bottomanchors. horizontalCenter: _progress. horizontalCenteranchors. topMargin: 20 text: qsTr ( "开始复制" ) onClicked: { console. log ( "开始复制" ) 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) ;
# 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. 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++代码
创建两个类 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