Qt之QFutureWatcher
来源:互联网 发布:淘宝相机镜头十大黑店 编辑:程序博客网 时间:2024/06/04 18:03
简述
QFuture 表示异步计算的结果,QFutureWatcher 则允许使用信号和槽监视 QFuture,也就是说,QFutureWatcher 是为 QFuture 而生的。
- 简述
- 详细描述
- 基本使用
- 更多参考
详细描述
QFutureWatcher 提供了有关 QFuture 的信息和通知,使用 setFuture() 函数开始监视一个特定的 QFuture,函数 future() 则返回由 setFuture() 设置的 future。
为了方便,QFuture 的很多函数可以直接通过 QFutureWatcher 来访问,例如:progressValue()、progressMinimum()、progressMaximum()、progressText()、isStarted()、isFinished()、isRunning()、isCanceled()、isPaused()、waitForFinished()、result() 和 resultAt()。而 cancel()、setPaused()、pause()、resume() 和 togglePaused() 是 QFutureWatcher 中的槽函数。
状态更改由 started()、finished()、cancelled()、paused()、resumed()、resultReadyAt() 和 resultsReadyAt() 信号提供,进度信息由 progressRangeChanged()、progressValueChanged() 和progressTextChanged() 信号提供。
由函数 setPendingResultsLimit() 提供节流控制。当挂起的 resultReadyAt() 或 resultsReadyAt() 信号数量超过限制时,由 future 表示的计算将被自动节流。一旦挂起的信号数量下降到限制以下时,计算将恢复。
示例,开始计算并当完成时获取槽回调:
// 实例化对象,并连接到 finished() 信号。MyClass myObject;QFutureWatcher<int> watcher;connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));// 开始计算QFuture<int> future = QtConcurrent::run(...);watcher.setFuture(future);
基本使用
来看一个图像加载和缩放的示例。选择多个图片,进行异步计算(将所有图片进行缩放),加载过程中可以显示进度,以便我们实时了解进展。每当一个图片处理完成,就会显示在窗体中。
这里仅为了演示效果,加载了 8 张 图片。
具体的源码如下所示:
ImagesView.h:
#ifndef IMAGES_VIEW_H#define IMAGES_VIEW_H#include <QFutureWatcher>#include <QWidget>class QLabel;class QPushButton;class QVBoxLayout;class QGridLayout;class ImagesView : public QWidget{ Q_OBJECTpublic: explicit ImagesView(QWidget *parent = 0); ~ImagesView();private slots: void open(); // 打开目录,加载图片 void showImage(int index); // 显示图片 void finished(); // 更新按钮状态private: QPushButton *m_pOpenButton; QPushButton *m_pCancelButton; QPushButton *m_pPauseButton; QVBoxLayout *m_pMainLayout; QGridLayout *m_pImagesLayout; QList<QLabel *> labels; QFutureWatcher<QImage> *m_pWatcher;};#endif // IMAGES_VIEW_H
下面是实现部分,c_nImageSize 表示的是图片被缩放的大小(宽度:100 px,高度:100px),函数 scale() 则是对图片缩放的具体实现。
ImagesView.cpp
#include <QLabel>#include <QPushButton>#include <QProgressBar>#include <QFileDialog>#include <QtConcurrent/QtConcurrentMap>#include <QStandardPaths>#include <QHBoxLayout>#include <qmath.h>#include "ImagesView.h"const int c_nImageSize = 100;// 缩放图片QImage scale(const QString &imageFileName){ QImage image(imageFileName); return image.scaled(QSize(c_nImageSize, c_nImageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);}ImagesView::ImagesView(QWidget *parent) : QWidget(parent){ setWindowIcon(QIcon(":/Images/logo")); setWindowTitle(QStringLiteral("Qt之QFutureWatcher")); resize(800, 600); // 初始化控件 m_pWatcher = new QFutureWatcher<QImage>(this); m_pOpenButton = new QPushButton(QStringLiteral("打开图片")); m_pCancelButton = new QPushButton(QStringLiteral("取消")); m_pPauseButton = new QPushButton(QStringLiteral("暂停/恢复")); QProgressBar *pProgressBar = new QProgressBar(this); m_pCancelButton->setEnabled(false); m_pPauseButton->setEnabled(false); // 布局 QHBoxLayout *pButtonLayout = new QHBoxLayout(); pButtonLayout->addWidget(m_pOpenButton); pButtonLayout->addWidget(m_pCancelButton); pButtonLayout->addWidget(m_pPauseButton); pButtonLayout->addStretch(); pButtonLayout->setSpacing(10); pButtonLayout->setMargin(0); m_pImagesLayout = new QGridLayout(); m_pMainLayout = new QVBoxLayout(); m_pMainLayout->addLayout(pButtonLayout); m_pMainLayout->addWidget(pProgressBar); m_pMainLayout->addLayout(m_pImagesLayout); m_pMainLayout->addStretch(); m_pMainLayout->setSpacing(10); m_pMainLayout->setContentsMargins(10, 10, 10, 10); setLayout(m_pMainLayout); // 连接信号槽 - 加载、显示进度、打开、取消等操作 connect(m_pWatcher, SIGNAL(resultReadyAt(int)), SLOT(showImage(int))); connect(m_pWatcher, SIGNAL(progressRangeChanged(int,int)), pProgressBar, SLOT(setRange(int,int))); connect(m_pWatcher, SIGNAL(progressValueChanged(int)), pProgressBar, SLOT(setValue(int))); connect(m_pWatcher, SIGNAL(finished()), SLOT(finished())); connect(m_pOpenButton, SIGNAL(clicked()), SLOT(open())); connect(m_pCancelButton, SIGNAL(clicked()), m_pWatcher, SLOT(cancel())); connect(m_pPauseButton, SIGNAL(clicked()), m_pWatcher, SLOT(togglePaused()));}ImagesView::~ImagesView(){ m_pWatcher->cancel(); m_pWatcher->waitForFinished();}// 打开目录,加载图片void ImagesView::open(){ // 如果已经加载图片,取消并进行等待 if (m_pWatcher->isRunning()) { m_pWatcher->cancel(); m_pWatcher->waitForFinished(); } // 显示一个文件打开对话框 QStringList files = QFileDialog::getOpenFileNames(this, QStringLiteral("选择图片"), QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), "*.jpg *.png"); if (files.count() == 0) return; // 做一个简单的布局 qDeleteAll(labels); labels.clear(); int dim = qSqrt(qreal(files.count())) + 1; for (int i = 0; i < dim; ++i) { for (int j = 0; j < dim; ++j) { QLabel *pLabel = new QLabel(this); pLabel->setFixedSize(c_nImageSize, c_nImageSize); m_pImagesLayout->addWidget(pLabel, i, j); labels.append(pLabel); } } // 使用 mapped 来为 files 运行线程安全的 scale 函数 m_pWatcher->setFuture(QtConcurrent::mapped(files, scale)); m_pOpenButton->setEnabled(false); m_pCancelButton->setEnabled(true); m_pPauseButton->setEnabled(true);}// 显示图片void ImagesView::showImage(int index){ labels[index]->setPixmap(QPixmap::fromImage(m_pWatcher->resultAt(index)));}// 更新按钮状态void ImagesView::finished(){ m_pOpenButton->setEnabled(true); m_pCancelButton->setEnabled(false); m_pPauseButton->setEnabled(false);}
构造函数中,需要注意的是槽函数,其中 resultReadyAt() 表示 index 对应位置的处理结果已准备就绪,所以连接该信号至槽函数 showImage(),可以显示处理完的图片。
为了显示处理进度,我们构造了一个进度条,当 QFutureWatcher 的 progressRangeChanged() 的信号发射时,进度条的范围会发生改变,而 progressValueChanged() 信号发射时,会更新进度条的值。
如果加载的图片较多时,可以通过点击“取消”按钮,这时会调用 QFutureWatcher 的 cancel() 槽函数来取消计算。“暂停/恢复”则调用 togglePaused() 槽函数,用于切换异步计算的暂停状态,换句话说,如果计算当前已暂停,调用此函数将进行恢复;如果计算正在运行,则会暂停。
当点击“打开”按钮时,会调用槽函数 open(),默认打开图片目录,以便进行图片的选择。然后根据图片创建对应数量的标签 QLabel,用于显示后期缩放的图片。创建完成后,使用 mapped() 进行并行计算,并添加至 QFutureWatcher 中,让其使用信号和槽监视 QFuture。
接下来,就可以直接使用了。
#include <QApplication>#include "ImagesView.h"int main(int argc, char *argv[]){ QApplication app(argc,argv); ImagesView view; view.show(); return app.exec();}
这样,我们就完成了一个图片缩放加载缩放的功能。
更多参考
- Qt之Concurrent框架
- Qt之Concurrent Map和Map-Reduce
- Qt之Concurrent Filter和Filter-Reduce
- Qt之Concurrent Run
- Qt之QFuture
- Qt之QFutureWatcher
- [Qt] QFuture和QFutureWatcher
- QFutureWatcher
- QFuture QFutureWatcher
- QFutureWatcher QFuture
- QFutureWatcher 可以使用信号
- qt学习之qt creator
- qt学习之qt安装
- Qt基础之hello qt
- Qt之Qt::WA_DeleteOnClose详解
- Qt|Qt之鼠标样式
- Qt 之 Qt Charts 模块
- qt学习之qtableview
- 开始Qt之旅
- Qt之对话框
- QT之正则表达式
- QT之QGroupBox
- Qt之文件操作
- jquery读取当前页面的所有cookie
- 原型模式-Prototype Pattern 对象的克隆——原型模式(一):大同小异的工作周报,原型模式概述
- 还不如看看庄子的大智慧
- Object-C之词典(NSDictionary, NSMutableDictionary)
- LeetCode 191. Number of 1 Bits
- Qt之QFutureWatcher
- iOS扩大按钮UIButton的点击范围
- eclipse中导入项目外部的jar包时出现.classpath can`t be write
- ubuntu 安装uget—+aria2并且在火狐中将其设置为默认的下载器
- 【PAT甲级】1046. Shortest Distance (20)
- iOS 自定义输入键盘
- Python内建函数:sorted
- 非常Strong的编程学习方法
- shc对Shell脚本加密方法及问题处理