一、项目要求
使用线程完善文件拷贝器的操作
- 主窗口不能假死
- 主窗口进度条必须能动
- 改写文件大小的单位(自适应)
1TB=1024GB
1GB=1024MB
1MB=1024KB
1KB=1024字节
二、所需技术
1.QFileDialog 文件对话框
QFileDialog也继承了QDialog类,直接使用静态成员函数弹窗,弹窗的结果(选择文件的路径)通过函数的返回值获取。
// 获得一个打开或保存的文件路径
// 参数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 文件信息类
只需要创建出对象后,通过各种成员函数直接获取文件信息。
// 构造函数
// 参数为文件路径,如果文件非法,仍然可以创建出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相关接口,这些接口虽然在不同的派生类中可能是实现有区别,但调用方式一致。
// 构造函数
// 参数为文件路径,如果是非法路径,也能创建出对象,但是不能正常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界面
三、代码
//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
//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
//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,"通知","文件拷贝完毕");
}
}
//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() << "资源已释放";
}