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() << "资源已释放";
 
}

四、实验结果

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript