首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt5.15:如何从QtConcurrent函数访问小部件对象

Qt5.15:如何从QtConcurrent函数访问小部件对象
EN

Stack Overflow用户
提问于 2020-08-06 22:20:14
回答 1查看 99关注 0票数 0

我希望从QtConcurrent函数更新进度栏小部件,并解决了以下问题:

a)如果我将此函数声明为:

代码语言:javascript
复制
void myRunFunction(QString str)

然后,我通过以下方式成功地将其编程为并发:

代码语言:javascript
复制
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));

但是我不能从函数内部访问我的GUI的任何Qt部件(“无法解析标识符' widget‘")。

b)如果我将此函数声明为:

代码语言:javascript
复制
void mainForm::myRunFunction(QString str)

然后,我成功地访问了它内部的小部件,但不能再将其编程为并发的,因为得到了编译器错误:

代码语言:javascript
复制
error: invalid use of non-static member function ‘void mainForm::myRunFunction(QString)’

在第1行:

代码语言:javascript
复制
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));

我该如何解决这个问题?非常感谢你,马可

EN

回答 1

Stack Overflow用户

发布于 2020-08-06 22:33:08

在Qt中,所有小部件都应该驻留在主GUI线程中。所有其他线程都不应该直接从主线程访问widgets,Qt在这里不保证线程安全。解决方案是什么?使用Qt的内置队列机制。有两种方法。

  1. 如果第二个线程中有QObject派生类,则可以使用Qt::QueuedConnection Qt::signal/slot连接。您也可以使用Qt::AutoConnection,这是默认设置,但我更喜欢明确说明我需要什么。

来自文档:

(Qt::AutoConnection)如果接收器位于发出信号的线程中,则使用Qt::DirectConnection。否则,将使用Qt::QueuedConnection。当发出信号时,确定连接类型。

如果您的第二个线程中没有任何QMetaObject::invokeMethod.,请使用

如何为调用者提供指向被调用者的指针?我推荐使用闭包(带有捕获的lambda )。

但是要注意对象的生命周期。现在由您负责检查捕获的小部件指针指向有效小部件的时间是否长于非GUI线程的生命周期。

根据您的代码,第二个变体更适合您。这里有一个小例子:

代码语言:javascript
复制
// guiwidget.h
class GuiWidget : public QWidget
{
    Q_OBJECT

public:
    GuiWidget(QWidget *parent = nullptr);
    ~GuiWidget() {};

   // public function for variant 2
   void function(int data) {
      // update widget
   }

// slot for variant 1
public slots:
    void function_slot(int data) {
        // update widget
    }
};

在您的.cpp文件中的某个位置:

代码语言:javascript
复制
GuiWidget *widget = new GuiWidget(this);
// declare a lambda
auto f = [widget] (QString str) 
{
    for (int i = 0; i < str.toInt(); ++i) {
        // do some job
        // ...
        // job is done
        // send progress data to mainwidget
        QMetaObject::invokeMethod(widget, [widget, i] () 
        {
            widget->function(i);
        }, Qt::QueuedConnection);
    }
};

auto t1 = QtConcurrent::run(f, "100");
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63285615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档