我正在制作一个在Qt中复制文件的程序。我想知道如何将QProgressBar
与bool QFile::copy(const QString & fileName, const QString & newName)
一起使用。这可能是copy
功能吗?是否可以暂停复制过程?
答案 0 :(得分:3)
您无法使用静态QFile :: copy()方法执行此操作。
正如Maciej之前所说,你需要写自己的课程。它应该使用两个QFile对象,一个用于读取一个用于写入。分批传输数据(例如整个文件大小的1%)并在每个部分之后发出进度信号。您可以将此信号连接到进度对话框。
如果您需要在后台工作,则应使用QThread实现它。
首先尝试确定是否需要一个能够异步(不阻止GUI)或同步(阻止GUI)的复制工作的类。后者更容易编程,但大多数时候不是预期的(例如,如果GUI被阻止,你不能通过按钮点击取消或暂停复制操作。)
你可以在这里查看相当广泛的Qt 4课程:http://docs.huihoo.com/qt/solutions/4/qtcopydialog/qtfilecopier.html但我不确定这是否会因其复杂性而有所帮助。
答案 1 :(得分:1)
这是一个显示的最小示例:
filecopyer.h
:
/*
* This is a minimal example to show thread-based QFile copy operation with progress notfication.
* See here for QFile limitations: https://doc.qt.io/qt-5/qfile.html#platform-specific-issues
* Copyright (C) 2019 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _FILE_COPYER_H
#define _FILE_COPYER_H
#include <QtCore/qstring.h>
#include <QtCore/qobject.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qvector.h>
#include <QtCore/qthread.h>
class FileCopyer : public QObject {
Q_OBJECT
Q_PROPERTY(qint64 chunksize READ chunkSize WRITE setChunkSize)
Q_PROPERTY(QVector<QString> sourcePaths READ sourcePaths WRITE setSourcePaths)
Q_PROPERTY(QVector<QString> destinationPaths READ destinationPaths WRITE setDestinationPaths)
public:
static const int DEFAULT_CHUNK_SIZE = 1024 * 1024 * 1;
FileCopyer(QThread*);
~FileCopyer();
qint64 chunkSize() const {
return _chunk;
}
void setChunkSize(qint64 ch) {
_chunk = ch;
}
QVector<QString> sourcePaths() const {
return src;
}
void setSourcePaths(const QVector<QString>& _src) {
src = _src;
}
QVector<QString> destinationPaths() const {
return dst;
}
void setDestinationPaths(const QVector<QString>& _dst) {
dst = _dst;
}
protected slots:
void copy();
private:
QVector<QString> src, dst;
qint64 _chunk;
signals:
void copyProgress(qint64 bytesCopied, qint64 bytesTotal);
void finished(bool success);
};
#endif // !_FILE_COPYER_H
filecopyer.cpp
:
/*
* This is a minimal example to show thread-based QFile copy operation with progress notfication.
* See here for QFile limitations: https://doc.qt.io/qt-5/qfile.html#platform-specific-issues
* Copyright (C) 2019 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <QtCore/qdebug.h>
#include "filecopyer.h"
FileCopyer::FileCopyer(QThread* _thread) :QObject(nullptr) {
moveToThread(_thread);
setChunkSize(DEFAULT_CHUNK_SIZE);
QObject::connect(_thread, &QThread::started, this, &FileCopyer::copy);
QObject::connect(this, &FileCopyer::finished, _thread, &QThread::quit);
QObject::connect(this, &FileCopyer::finished, this, &FileCopyer::deleteLater);
QObject::connect(_thread, &QThread::finished, _thread, &QThread::deleteLater);
}
FileCopyer::~FileCopyer() {
}
void FileCopyer::copy() {
if (src.isEmpty() || dst.isEmpty()) {
qWarning() << QStringLiteral("source or destination paths are empty!");
emit finished(false);
return;
}
if (src.count() != dst.count()) {
qWarning() << QStringLiteral("source or destination paths doesn't match!");
emit finished(false);
return;
}
qint64 total = 0, written = 0;
for (const auto& f : src)
total += QFileInfo(f).size();
qInfo() << QStringLiteral("%1 bytes should be write in total").arg(total);
int indx = 0;
qInfo() << QStringLiteral("writing with chunk size of %1 byte").arg(chunkSize());
while (indx < src.count()) {
const auto dstPath = dst.at(indx);
QFile srcFile(src.at(indx));
QFile dstFile(dstPath);
if (QFile::exists(dstPath)) {
qInfo() << QStringLiteral("file %1 alreasy exists, overwriting...").arg(dstPath);
QFile::remove(dstPath);
}
if (!srcFile.open(QFileDevice::ReadOnly)) {
qWarning() << QStringLiteral("failed to open %1 (error:%1)").arg(srcFile.errorString());
indx++;
continue; // skip
}
if (!dstFile.open(QFileDevice::WriteOnly)) {
qWarning() << QStringLiteral("failed to open %1 (error:%1)").arg(dstFile.errorString());
indx++;
continue; // skip
}
/* copy the content in portion of chunk size */
qint64 fSize = srcFile.size();
while (fSize) {
const auto data = srcFile.read(chunkSize());
const auto _written = dstFile.write(data);
if (data.size() == _written) {
written += _written;
fSize -= data.size();
emit copyProgress(written, total);
} else {
qWarning() << QStringLiteral("failed to write to %1 (error:%2)").arg(dstFile.fileName()).arg(dstFile.errorString());
fSize = 0;
break; // skip this operation
}
}
srcFile.close();
dstFile.close();
indx++;
}
if (total == written) {
qInfo() << QStringLiteral("progress finished, %1 bytes of %2 has been written").arg(written).arg(total);
emit finished(true);
} else {
emit finished(false);
}
}
main.cpp
:
#include <QtWidgets/QApplication>
#include "filecopyer.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
auto local = new QThread;
auto worker = new FileCopyer(local);
QObject::connect(worker, &FileCopyer::finished, [](bool s) {
s ? qDebug() << "FINISHED" : qDebug() << "FAILED";
});
QObject::connect(worker, &FileCopyer::copyProgress, [](qint64 copy, qint64 total) {
qDebug() << QStringLiteral("PROGRESS => %1").arg(qreal(copy) / qreal(total) * 100.0);
});
worker->setSourcePaths(/* src-paths */); // e.g: ~/content/example.mp4
worker->setDestinationPaths(/* dst-paths */); // e.g /usr/local/example.mp4
local->start();
return a.exec();
}
答案 2 :(得分:-1)
查看QFile
从[{3}}派生的课程,有一个信号bytesWritten()
连接到该课程并通过QFileInfo(fromFile).size()
统计文件大小以获取有关如何使用的信息信号检查我的其他QIODevice