QT多线程文件拷贝器

项目要求:

        1、主窗口不能卡死

        2、窗口进度条要动

        3、自适应改动文件大小的单位

        4、有停止和暂停功能

流程图:

界面UI

项目源码:

主线程:

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    btngroup=new QButtonGroup(this);
    btngroup->addButton(ui->pushButtonOpen,1);
    btngroup->addButton(ui->pushButtonSave,2);
    btngroup->addButton(ui->pushButtonStart,3);
    btngroup->addButton(ui->pushButtonClearInfo,4);
    btngroup->addButton(ui->pushButtonStop,5);
    btngroup->addButton(ui->pushButtonClearSave,6);
    btngroup->addButton(ui->pushButtonClearOpen,7);
    copy=new ThreadCopy(this);
    connect(btngroup,SIGNAL(buttonClicked(int)),SLOT(btnClickedSlot(int)));
    connect(copy,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));
}
Dialog::~Dialog()
{
    delete ui;
    delete copy;
}
void Dialog::btnClickedSlot(int id)
{
    if(id==1)
    {
        QString filter="所有文件(*.*);;C++(*.h *.cpp *.hpp)";
        readPath=QFileDialog::getOpenFileName(this,"打开","C:/",filter);
        //将文本框中内容转换成字符串并判断信息文本框是否为空,不为空则清除后重新写入文件信息
        bool clearInfo=ui->textBrowserInfo->toPlainText().isEmpty();
        //qDebug()<<clearInfo.isEmpty();
        if(!clearInfo)
        {
            ui->textBrowserInfo->clear();
        }
        bool clearTextOpen=ui->textBrowserOpen->toPlainText().isEmpty();
        if(!clearTextOpen)
        {
            ui->textBrowserOpen->clear();
        }
        ui->textBrowserOpen->append(readPath);
        readFileInfo();
        copy->getReadPath(readPath);

    }
    else if(id==2)
    {
        QString filter="所有文件(*.*);;C++(*.h *.cpp *.hpp)";
        writePath=QFileDialog::getSaveFileName(this,"保存","C:/",filter);
        bool clearTextSave=ui->textBrowserSave->toPlainText().isEmpty();
        if(!clearTextSave)
        {
            ui->textBrowserSave->clear();
        }
        ui->textBrowserSave->append(writePath);
        copy->getWritePath(writePath);
    }
    else if(id==3)
    {
        if(readPath=="")
        {
            QMessageBox::warning(this,"警告","请选择要打开的文件!");
            return;
        }
        if(writePath=="")
        {
            QMessageBox::warning(this,"警告","请选择要保存的路径!");
            return;
        }
        if(ui->pushButtonStart->text() == "开始")
        {
            copy->getReadPath(readPath);
            copy->getWritePath(writePath);
            copy->setRunningState(true);
            ui->pushButtonStart->setText("暂停");
            //开始子线程拷贝和UI变动
            copy->start();
        }
        else
        {
            ui->pushButtonStart->setText("开始");
            copy->setRunningState(false);
        }
    }
    else if(id==4)
    {
        ui->textBrowserInfo->clear();
    }
    else if(id==5)
    {

        ui->progressBar->setValue(0);
        copy->setRunningState(false);
        copy->setWriteSize(0);
        //恢复开始按钮
        ui->pushButtonStart->setEnabled(true);
        ui->pushButtonStart->setText("开始");

    }
    else if(id==6)
    {
        ui->textBrowserSave->clear();
    }
    else if(id==7)
    {
        ui->textBrowserOpen->clear();

    }
}
void Dialog::readFileInfo()
{
    // 创建文件信息类对象
    QFileInfo fileInfo(readPath);
    if(!fileInfo.exists())
        return;
    QString text=fileInfo.baseName();
    text.prepend("文件名称:");
    ui->textBrowserInfo->append(text);

    text = fileInfo.lastModified().toString("修改时间: yyyy-MM-dd hh:mm:ss");
    ui->textBrowserInfo->append(text);

    qint64 size = fileInfo.size();

    sizelist={"B","KB","MB","GB","TB"};
    int units_count=0;
    double sizedouble=static_cast<double>(size);

    while(sizedouble>1024&&units_count<sizelist.size()-1)
    {
        sizedouble = sizedouble/1024;
        ++units_count;
    }
    text = QString::number(sizedouble,'g',3);
    text.prepend("文件大小:").append(sizelist.at(units_count));
    ui->textBrowserInfo->append(text);

    // 获得可读性
    if(fileInfo.isReadable())
        ui->textBrowserInfo->append("文件可读");
    else
        ui->textBrowserInfo->append("文件不可读");
}
void Dialog::valueSlot(int value)
{
    ui->progressBar->setValue(value);
    if(value == 100)
    {
        this->hide();
        this->show();
        QMessageBox::information(this,"提示","拷贝完成");
        disconnect(copy, SIGNAL(valueSignal(int)), this, SLOT(valueSlot(int)));//断开连接释放资源
        delete copy;//清除旧的堆区对象
        copy=new ThreadCopy(this);
        connect(copy,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));
        ui->pushButtonStart->setText("开始");
        ui->progressBar->setValue(0);
    }
}

子线程:

#include "threadcopy.h"

ThreadCopy::ThreadCopy(QObject *parent) : QThread(parent),runningState(true),writesize(0)
{

}

ThreadCopy::~ThreadCopy()
{

}
bool ThreadCopy::getRunningState() const
{
    return runningState;
}

void ThreadCopy::setRunningState(bool value)
{
    runningState = value;
}

void ThreadCopy::getWritePath(QString fatherWritePath)
{
    this->writePath = fatherWritePath;
}

void ThreadCopy::setWriteSize(int a)
{
    this->writesize=a;
}

void ThreadCopy::getReadPath(QString fatherReadPath)
{
    this->readPath = fatherReadPath;
}

void ThreadCopy::run()
{

    QFile readFile(readPath);
    QFile writeFile(writePath);
    readFile.open(QIODevice::ReadOnly);
    writeFile.open(QIODevice::WriteOnly|QIODevice::Append);
    //字节数组类
    QByteArray array;
    //读取的字节
    qint64 totalsize = readFile.size();
    readFile.seek(writesize);
    writeFile.seek(writesize);
    while(!readFile.atEnd())
    {
        if(!runningState)
        {
            return;
        }

        //读取数据
        array=readFile.read(1024);
        //写出数据
        writesize+=writeFile.write(array);
        //计算百分比
        qint64 value=100 * writesize/totalsize;
        //设置给进度条
        emit valueSignal(value);// 发射自定义信号
    }

    //清空缓存区
    writeFile.flush();

    //关闭文件流
    readFile.close();
    writeFile.close();
}

讲解:

QT文件拷贝器思路讲解_哔哩哔哩_bilibili

### 回答1: qt多线程文件拷贝进度条程序的下载,在这里我将简单介绍一下实现的思路与步骤。 首先,在使用Qt进行多线程文件拷贝与进度显示之前,我们需要引入Qt的相关头文件,例如QFile、QThread等。 接下来,我们需要创建一个自定义的线程类,继承自QThread。在这个线程类中,我们需要重写run()函数,在run()函数中实现文件拷贝操作。具体的拷贝操作可以使用QFile类中的copy()函数。 为了实现进度条的显示,我们可以通过信号与槽机制来实现。我们可以在自定义的线程类中定义一个信号,用来传递文件拷贝的进度。可以使用QFile类的size()函数获取文件的总大小,然后在每次拷贝一个块的时候,发送一个信号,参数为已拷贝的字节数,通过计算已拷贝字节数和文件总大小的比例,来计算拷贝的进度。 在主线程或主窗口类中,我们需要创建一个进度条控件用于显示拷贝的进度。然后连接自定义的线程中的信号与主线程中的槽函数,以更新进度条的进度。 在点击开始拷贝按钮的时候,我们需要创建一个自定义的线程对象,并调用start()函数启动线程。然后在槽函数中处理接收到的信号,更新进度条的进度。 以上就是实现qt多线程文件拷贝进度条程序的简要步骤。通过多线程的方式进行文件拷贝,可以使程序在拷贝较大文件时不会出现界面卡顿的情况,同时通过进度条可以直观地显示拷贝的进度。 ### 回答2: 对于Qt多线程文件拷贝进度条程序的下载,我们可以采用如下步骤: 1. 首先,在Qt中创建一个新的工程,添加一个进度条控件和一个按钮控件。 2. 在主线程中点击按钮事件的槽函数中,创建一个新的子线程,并传递需要拷贝文件路径和目标路径作为参数。 3. 在子线程中,使用Qt文件操作类QFile进行文件拷贝。通过打开源文件,创建目标文件并复制源文件内容到目标文件中,实现文件拷贝的功能。 4. 在拷贝文件的过程中,可以在子线程中实时更新进度条的值,并通过信号和槽机制将进度条的值传递给主线程。 5. 在主线程中,接收并处理来自子线程的进度条值变化的信号,实时更新界面上的进度条的显示。 6. 当文件拷贝完成后,子线程发送一个完成信号给主线程,主线程处理该信号,提示文件拷贝已完成。 7. 最后,通过Qt的信号和槽机制,将按钮的点击事件和文件拷贝的相关操作进行连接,使得点击按钮时可以启动文件拷贝进度条程序的下载。 通过以上步骤,我们可以实现一个基于Qt多线程、带有进度条的文件拷贝程序。用户可以通过点击界面上的按钮来触发拷贝过程,并实时显示拷贝的进度。这样可以提高文件拷贝的效率,并提供更好的用户体验。 ### 回答3: Qt是一种跨平台的C++应用程序开发框架,它提供了丰富的功能库和工具,可以帮助开发者快速构建各种类型的应用程序。在Qt中,我们可以使用多线程来实现文件拷贝功能,并在界面上显示一个进度条,以便用户能够清楚地了解文件拷贝的进度。 首先,我们需要创建一个继承自QThread的自定义类,用于执行文件拷贝的操作。在这个类中,我们可以重写run()函数,在函数中执行拷贝文件的逻辑。在拷贝文件的过程中,我们可以通过信号机制来实时发送拷贝进度给主线程。 在主线程中,我们可以创建一个进度条控件,并与自定义的文件拷贝线程进行连接。当文件拷贝线程发送进度信号时,我们可以更新进度条的值,让用户能够实时观察到文件拷贝的进度。 同时,我们还可以提供一些用户交互的功能,比如添加文件、选择目标文件夹等。这些功能可以通过Qt的信号与槽机制来实现,用户可以触发相应的信号,然后我们在槽函数中执行相应的操作,比如选择文件,选择目标文件夹等。 除此之外,为了防止文件拷贝操作过程中出现的各种异常情况,我们还可以在文件拷贝线程中进行错误处理和异常捕获,并通过信号与槽机制向主线程发送错误信息,以便及时通知用户。 总而言之,通过Qt多线程和信号与槽机制,我们可以简单地实现一个多线程文件拷贝进度条程序的下载功能。这样用户可以在界面上直观地看到文件拷贝的进度,并能够通过界面交互实现文件选择和目标文件夹选择等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值