Qt:后台线程刷新UI线程

eba*_*onp 9 c++ qt4

我有一个后台线程,线程调用一些更新UI的方法(为了显示进度条并在文本区域显示其他信息).

如果我修改了一些UI窗口小部件值,则会引发"无法将事件发送到由不同线程拥有的对象"断言错误.

看看论坛,我读到我可以使用QMetaObject :: invokeMethod方法,但是如果我传递Qt :: DirectConnection标志,它实际上会引发上面显示的相同错误,它就可以正常工作.

如果我使用Qt :: QueuedConnection或Qt :: AutoConnection,则invokeMethod返回false.

我的代码看起来类似于:

.H:

class A : public QMainWindow
{
  Q_OBJECT

  QProgressBar* pb;

  public slots:
    bool m(bool, int);
};

class B
{
  A* a;

  public:
    void handleEvent();
};


.cpp:

bool A::m(bool x, int y)
{
  pb->setValue(y);
  return x;
}

void B::handleEvent()
{
  //a->m(true, 12); //raises an assertion error

  bool r;
  //bool ret = QMetaObject::invokeMethod(a, "m", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //raises the same assertion error error

  bool ret = QMetaObject::invokeMethod(a, "m", Qt::AutoConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //is ignored and ret contains false.
}
Run Code Online (Sandbox Code Playgroud)

你知道发生了什么事或我做错了什么吗?或者,有人可以建议我另一种处理我的新手问题的方法吗?

提前致谢,

埃内斯托

Jas*_*n B 10

我没有用过invokeMethod()自己,但为了做到这一点,我通常只使用信号和插槽.例如,您可以创建一个信号作为class B连接到插槽的成员,以class A更新进度:

class B : public QObject
{
    Q_OBJECT

    A* a;

signals:
    void update_signal(bool, int);

public:
    void handleEvent();
};

B::B()
{
    //assuming a already points to the correct place...
    connect(this, SIGNAL(update_signal(bool,int), 
            a, SLOT(m(bool,int)), Qt::QueuedConnection);
}

void B::handleEvent()
{
    emit update_signal(true, 12);
}
Run Code Online (Sandbox Code Playgroud)

A::m()将不得不在这种情况下返回void但由于使用排队连接时,你不能得到一个返回值反正这不是一个问题,因为调用是异步的(emit update_signal(true,12)可能会返回被称为插槽功能之前,根本不可能有返回值准备).

实际上,你只要能在任何地方,你有一个指针执行此连接类型的对象A和类型的对象B.这使得信号和槽非常灵活,因为你可以完全脱钩AB,但仍然允许他们通过信号和槽沟通.例如:

class B : public QObject
{
    Q_OBJECT

signals:
    void update_signal(bool, int);

public:
    void handleEvent();
};

void B::handleEvent()
{
    emit update_signal(true, 12);
}

class A : public QMainWindow
{
    Q_OBJECT

    QProgressBar* pb;

    public slots:
        void m(bool, int);
};

void A::m(bool x, int y)
{
    pb->setValue(y);
}

int main()
{
    A* a = new A();
    B* b = new B();

    QObject::connect(b, SIGNAL(update_signal(bool, int)),
            a, SLOT(m(bool, int)), Qt::QueuedConnection);

    //...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,b不必存储指针或知道任何有关a它们可以通过精心定义的精简通道进行通信的信息.