【问题标题】:How to communicate a progressText from a QtConcurrent::run function (or similar) to a QFutureWatcher?如何将 QtConcurrent::run 函数(或类似函数)中的 progressText 传递给 QFutureWatcher?
【发布时间】:2014-05-02 22:45:00
【问题描述】:

如果我使用QtConcurrent::run 启动某个异步执行函数,并使用QFutureWatcher 监视返回的未来,如果我可以在该异步执行函数中执行什么操作来传达一些进度文本,这将导致QFutureWatcher 发射其progressTextChanged 信号?

即我想做的是某事,比如:

void fn() {
  ???->setProgressText("Starting);
  ...
  ???->setProgressText("halfway");
  ...
  ???->setProgressText("done!");
}

QFutureWatcher watcher;
connect(&watcher, SIGNAL(progressTextChanged(const QString&)), &someGuiThing, SLOT(updateProgress(const QString&)));
connect(&watcher, SIGNAL(finished(), &someGuiThing, SLOT(doStuff()));
QFuture<void> future=QConcurrent::run(fn);
watcher.setFuture(future);

然而大问题,QtConcurrent::run documentation 明确说明

请注意,QtConcurrent::run() 返回的 QFuture 确实不支持 取消、暂停或进度报告。返回的 QFuture 可以 只用于查询运行/结束状态和返回 函数的值。

那么我能做的最简单的事情是什么,它可以让我在功能上与上述尝试做的事情相同?我必须放弃QtConcurrent::run吗? QFuture?两个都? (然后返回QThread 并排队连接?)

【问题讨论】:

    标签: c++ qt qt5 progress qtconcurrent


    【解决方案1】:

    QtConcurrent 函数(如QtConcurrent::mappedReduced())返回的QFuture 具有由progressValue()、progressMinimum()、progressMaximum() 和progressText() 函数提供的进度信息。不像QtConcurrent::run() 不会自动提供这样的东西。

    QtConcurrent::run() 不像QtConcurrent::mappedReduced() 那样自动提供进度信息。但是您可以使用信号拥有自己的进度报告机制。我认为没有其他直接的方法。

    【讨论】:

    • 好的,但是我实际上在fn() 中调用了什么来获取要更新的进度信息?显然,它需要传递一些东西……但是什么?似乎有一个 QFutureInterfaceBase 具有进度信息设置方法,但 QFuture 实际上并没有继承它。嗯...显然下一步是查看QtConcurrent::mappedReduced() 的实现,看看它是如何实现的...
    • 我认为使用信号报告进度是使用QtConcurrent::run()时最方便的方式。
    • 是的,这就是我最终做的事情:使用带有 QueuedConnection 的 QMetaObject::invokeMethod 从并发函数中发送状态消息到监视其进度的插槽(实际上, BlockingQueuedConnection 似乎导致显示更流畅......我发送了很多消息)。更多关于qt-project.org/forums/viewthread/41012/#174738的上下文@
    【解决方案2】:

    您仍然可以将QFutureWatcherQProgressDialog 一起使用,就像在我的示例中一样:

    void hole_mark::get_frames_with_progress(const QString& movie, const QString& output) {
        Ptr<cv::VideoCapture> source = makePtr<VideoCapture>(movie.toUtf8().constData());
    
        auto frames = (int)(source->get(CAP_PROP_FRAME_COUNT));
    
        QProgressDialog dialog(tr("Importing frames: %1...").arg(frames), tr("Cancel"), 0, frames, this);
        dialog.setWindowModality(Qt::WindowModal);
    
        QFutureWatcher<void> futureWatcherProgress;
        QFutureInterface<void> promise;
        QFuture<void> future = promise.future();
        promise.reportStarted();
    
        QObject::connect(&futureWatcherProgress, SIGNAL(finished()), &dialog, SLOT(reset()));
        QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcherProgress, SLOT(cancel()));
        QObject::connect(&futureWatcherProgress, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
        QObject::connect(&futureWatcherProgress, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int)));
        QObject::connect(&futureWatcherProgress, SIGNAL(progressTextChanged(const QString&)), &dialog, SLOT(setLabelText(const QString&)));
    
        futureWatcherProgress.setFuture(future);
        promise.setThreadPool(QThreadPool::globalInstance());
    
        auto runnable = QRunnable::create([&, frames, source]() {
    
            promise.setProgressRange(0, frames);
            promise.setProgressValue(0);
            cv::Mat m;
    
            int frame = 0;
    
            while (!future.isCanceled()) {
                *source >> m;
    
                if (m.empty()) {
                    break;
                }
    
                promise.setProgressValueAndText(++frame, tr("Importing %1 frame from: %2...").arg(frame).arg(frames));
    
                qDebug() << "frame: " << frame;
            }
    
    
            promise.reportFinished();
        });
    
        promise.setRunnable(runnable);
    
        QThreadPool::globalInstance()->start(runnable);
    
        // Display the dialog and start the event loop.
        dialog.exec();
    
        futureWatcherProgress.waitForFinished();
    
        // Query the future to check if was canceled.
        qDebug() << "Canceled?" << futureWatcherProgress.future().isCanceled();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      相关资源
      最近更新 更多