天天看点

QML复制文件并显示进度

效果:

QML复制文件并显示进度

 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      

继续阅读