我有一个程序,我现在正在将大的,1800万像素或更少的图像保存到磁盘上。一路上我将它们转换为QImage,在QDialog的子类中显示QImage,然后提示用户保存它们。
我想为用户提供某种进度指示器,所以我推断出我实现这一目标的最佳方法是创建一个QThread,在线程中使用worker保存图像,然后发出信号到GUI以声明保存已完成。我使用此方法在保存过程中向用户显示进度条。
在这里考虑这个简单的工人类:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QImage &image, const QString &file) {
if(image.save(file, "PNG", 100))
emit resultReady();
else
{
// handle error
return;
}
}
signals:
void resultReady();
};
我的问题是image :: save()函数经常在图像实际写入磁盘之前很久就返回true
。使用当前的代码行,在我的5600 HDD上,resultReady()
信号在用户按下按钮后大约6秒被触发,因此我的GUI更新以显示图像已完成保存。
但是,QImage似乎需要从7秒到30秒才能完成写入磁盘。在此期间,用户可能已经结束了应用程序,这会导致磁盘上的图像不完整,因为线程认为自己已完成。也许更糟糕的是,用户可能已经开始拍摄多张其他图像,这些图像开始加剧用于保存图像的持续时间。
有没有办法确定Qt应用程序何时完成将QImage写入硬盘?
答案 0 :(得分:2)
您对此问题的诊断不正确。一旦image.save
返回,文件系统就处于一致状态,您可以在此时强制退出应用程序:文件将具有正确的内容。 on-disk 状态是否一致是未知的,但所有这些意味着您不应该重置也不要强行关闭机器。不过,您的申请可以免费退出。
你的问题是别的。谁知道:您未能提供测试用例。
没有必要手动处理工作线程和对象。利用QtConcurrent
。这应该很容易,而且确实如此。即:
class MyWindow : public QWidget {
Q_OBJECT
CountDownLatch m_latch;
Q_SIGNAL void imageSaved(const QString & filename);
Q_SIGNAL void imageSaveFailed(const QString & filename);
void saveImage(const QImage & image, const QString & filename) {
auto lock = m_latch.lock();
QtConcurrent::run([=]{ // captures this, lock, image and filename
if (image.save(filename, "PNG", 100))
emit imageSaved(filename);
else
emit imageSaveFailed(filename);
});
}
...
// MyWindow's destructor will block until all image savers are done
};
有关CountDownLatch
的实施,请参阅this question。
答案 1 :(得分:0)
无论如何,处理主线程中的大数据是一个坏主意。对于这些问题,Qt框架提供了很好的工具。查看QConcurrent的Qt文档。 在您的情况下,我将使用 Concurrent Run 保存文件,以使用QFutureWatcher检索进度条的数据。
答案 2 :(得分:0)
@Ketta:你如何重现你的相同行为?也许是硬盘缓冲或其他原因。对于你的问题,我更喜欢更精细的方法,提供更多的控制。也许与
QImage image;
QFile file("file.png");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
image.save(&file, "PNG");
这可能为您提供控制数据写入的能力。 @Kuba:
connect( &m_futureWatcher, SIGNAL ( finished( ) ), this, SLOT( showText ( )) );
...... 和
m_futureFileReader = QtConcurrent::run(readFile, pIODevice );
m_futureWatcher.setFuture(m_futureFileReader);
作为阅读文本文件的一个例子对我来说似乎并不笨重。