qt--做一个拷贝文件器

一、项目要求

使用线程完善文件拷贝器的操作

  1. 主窗口不能假死
  2. 主窗口进度条必须能动
  3. 改写文件大小的单位(自适应)

1TB=1024GB

1GB=1024MB

1MB=1024KB

1KB=1024字节

二、所需技术

1.QFileDialog 文件对话框

QFileDialog也继承了QDialog类,直接使用静态成员函数弹窗,弹窗的结果(选择文件的路径)通过函数的返回值获取。

cpp 复制代码
// 获得一个打开或保存的文件路径
// 参数1 父对象
// 参数2 即windowTitle属性(界面标题)
// 参数3 在哪个目录下打开,默认值表示项目的工作目录
// 参数4 文件格式过滤器
// 返回值 选择的文件路径,如果选择失败,返回空字符
QString QFileDialog::​getSaveFileName|getOpenFileName
                (QWidget * parent = 0, 
                const QString & caption = QString(), 
                const QString & dir = QString(), 
                const QString & filter = QString())[static]

需要注意的是,QFileDialog只是一个窗口类,本身不具备任何IO能力。

2.QFileInfo 文件信息类

只需要创建出对象后,通过各种成员函数直接获取文件信息。

cpp 复制代码
// 构造函数
// 参数为文件路径,如果文件非法,仍然可以创建出QFileInfo
QFileInfo::​QFileInfo(const QString & file)

// 判断文件或文件夹是否存在
// 如果存在返回true否则返回false
bool QFileInfo::​exists() const

// 返回文件大小,单位是字节
qint64 QFileInfo::​size() const

// 返回基础文件名
QString QFileInfo::​baseName() const

// 返回最近修改日期和时间
QDateTime QFileInfo::​lastModified() const

// 返回可读性
bool QFileInfo::​isReadable() const

3.QFile文件读写类

在Qt中所有IO都都继承自QIODevice类,QIODevice类中规定了最基础的IO相关接口,这些接口虽然在不同的派生类中可能是实现有区别,但调用方式一致。

cpp 复制代码
// 构造函数
// 参数为文件路径,如果是非法路径,也能创建出对象,但是不能正常IO
QFile::​QFile(const QString & name)
 
// 判断QFile对应的文件是否存在
bool QFile::​exists() const
 

// 打开数据流
// 参数为打开的模式
// 返回值为打开的结果
bool QIODevice::​open(OpenMode mode)[virtual]
 
// 读取最大长度为maxSize个字节到返回值中
QByteArray QIODevice::​read(qint64 maxSize)
 
// 写出数据
// 参数为写出的内容
// 返回值为实际的数据写出字节数,出错返回-1
qint64 QIODevice::​write(const QByteArray & byteArray)
 
// 判断是否读到文件尾部
bool QIODevice::​atEnd() const[virtual]
 
// 关闭文件流
void QIODevice::​close()[virtual]
 
// 清空缓存区
bool QFileDevice::​flush()
 
// 返回输入流的大小,单位是字节
qint64 QIODevice::​size() const
 

4.ui界面

三、代码

cpp 复制代码
//dialog.h
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QFileDialog>
#include <QMessageBox>
#include <QDateTime>
#include <QFileInfo>
#include <QFile>
#include "mythread.h"
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QString readPath;
    QString writePath;
    void prinFileInfo();
    void copy();
    MyThread *ct;
private slots:
    void btnsClickedSlot();

   void valueSlot(int);
};

#endif // DIALOG_H
cpp 复制代码
//mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QDebug>
#include <QFile>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    ~MyThread();

     bool getRunningState() const;
     void setRunningState(bool value);
     void Pathget(QString, QString);

signals:
      void valueSignal(int);
public slots:

private:
      QString treadPath;
      QString twritePath;

    bool runningState;// 状态标记
protected:
    void run();
};

#endif // MYTHREAD_H
cpp 复制代码
//dialog.c
#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

connect(ui->pushButtonOpen,SIGNAL(clicked()),this,SLOT(btnsClickedSlot()));
connect(ui->pushButtonSave,SIGNAL(clicked()),this,SLOT(btnsClickedSlot()));
connect(ui->pushButtonCopy,SIGNAL(clicked()),this,SLOT(btnsClickedSlot()));


}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::prinFileInfo()
{
    QFileInfo info(readPath);
    if(!info.exists())
        return;
   qint64 size=info.size();

   qreal size2;
    QString text;
   if(size<1024)
   {
       size2=size;
       QString text=QString ::number(size2);
       text.prepend("文件大小:").append("字节");
       ui->textBrowserOpen->append(text);
   }
   else if(size>=1024 && size<1048576)
   {
    size2=size/1024;

    QString text=QString ::number(size2);
    text.prepend("文件大小:").append("K字节");
    ui->textBrowserOpen->append(text);
   }
   else if(size>=1048576&&size<1073741824)
   {
       size2=size/1048576;
       QString text=QString ::number(size2);
       text.prepend("文件大小:").append("M字节");
       ui->textBrowserOpen->append(text);
   }
   else if(size>=1073741824&&size<1099511627776)
   {
       size2=size/1073741824;
       QString text=QString ::number(size2);
       text.prepend("文件大小:").append("G字节");
       ui->textBrowserOpen->append(text);
   }

   text=info.baseName();
   text.prepend("文件名称:");
   ui->textBrowserOpen->append(text);

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

   bool result=info.isReadable();
   if(result)
       ui->textBrowserOpen->append("文件可读");
   else
       ui->textBrowserOpen->append("文件不可读");

}

void Dialog::copy()
{
    if(readPath=="")
    {
       QMessageBox::warning(this,"提示","请选择要读取的文件");
       return;

    }
    else if(writePath=="")
    {
        QMessageBox::warning(this,"提示","请选择要保存的文件");
        return;
    }

    QFile readFile(readPath);
    QFile writeFile(writePath);

    readFile.open(QIODevice::ReadOnly);
    writeFile.open(QIODevice::WriteOnly);

    writeFile.flush();
    readFile.close();
    writeFile.close();
}

void Dialog::btnsClickedSlot()
{

    if(ui->pushButtonOpen==sender())
    {
        QString filter="所有文件(*.*);;Qt(*.cpp *.pro *.h *.ui)";//符号都是英语符号,用于检索
        QString path=QFileDialog::getOpenFileName(this,"打开","C:/",filter);
         if(path != "")
        {
          ui->textBrowserOpen->append(path);
          readPath=path;
          prinFileInfo();
        }
             else if (readPath == "")
                        {
   QMessageBox::warning(this,"提示","请选择要打开的文件!");
                            return;
                        }

    }

    else if(ui->pushButtonSave==sender())
    {
        QString filter="所有文件(*.*);;Qt(*.cpp *.pro *.h *.ui)";
        QString path=QFileDialog::getSaveFileName(this,"保存","C:/",filter);
        if(path != "")
{
  ui->textBrowserSave->append(path);
  writePath=path;
}
     else if (writePath == "")
                {
                    QMessageBox::warning(this,"提示","请选择要保存的文件!");
                    return;
                }
    }
    else if(ui->pushButtonCopy==sender())
    {

        // 创建子线程对象并启动
          if(ui->pushButtonCopy->text() == "开始拷贝")
          {
               copy();
              ct = new MyThread(this);
              connect(ct,SIGNAL(valueSignal(int)),
                      this,SLOT(valueSlot(int)));
              ct->start();
              ui->pushButtonCopy->setText("停止拷贝");
          }
          else if (ui->pushButtonCopy->text() == "停止拷贝")
          {
              ui->pushButtonCopy->setText("开始拷贝");
              ct->setRunningState(false);
           }
    }
}
void Dialog::valueSlot(int value)
{
    ui->progressBar->setValue(value);
    if(value == 100)
    {
        // 释放按钮
        ui->pushButtonCopy->setEnabled(true);
        this->hide();// 隐藏主窗口,只是看不到
        this->show();// 显示主窗口
        QMessageBox::information(this,"通知","文件拷贝完毕");
    }
}
cpp 复制代码
//mythread.c
#include "mythread.h"

MyThread::MyThread(QObject *parent) : QThread(parent)
{
 setRunningState(true);
}

MyThread::~MyThread()
{

}

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

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


void MyThread::run()
{
    for(int i = 0 ;i <= 100 && runningState;i++)
    {
        QThread::msleep(100);
        emit valueSignal(i);
    }
    qDebug() << "资源已释放";
 
}

四、实验结果

相关推荐
Dontla6 分钟前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
Neophyte06081 小时前
C++算法练习-day40——617.合并二叉树
开发语言·c++·算法
慕容复之巅1 小时前
基于MATLAB的条形码的识别图像处理报告
开发语言·图像处理·matlab
zqzgng1 小时前
Python 数据可视化pilot
开发语言·python·信息可视化
写bug的小屁孩1 小时前
websocket初始化
服务器·开发语言·网络·c++·websocket·网络协议·qt creator
Dr_eamboat1 小时前
【Java】枚举类映射
java·开发语言·python
代码小鑫2 小时前
A031-基于SpringBoot的健身房管理系统设计与实现
java·开发语言·数据库·spring boot·后端
五味香2 小时前
Linux学习,ip 命令
linux·服务器·c语言·开发语言·git·学习·tcp/ip
欧阳枫落2 小时前
python 2小时学会八股文-数据结构
开发语言·数据结构·python
何曾参静谧2 小时前
「QT」文件类 之 QTextStream 文本流类
开发语言·qt