c++ - Qt : Background thread refreshing UI thread

标签 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.
}

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

提前致谢

埃内斯托

最佳答案

我自己没有使用过invokeMethod(),但为此,我通常只使用信号和槽。例如,您可以创建一个信号作为 B 类 的成员,该信号连接到 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);
}

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);

    //...
}

在这种情况下,b 不必存储指针或知道有关 a 的任何信息,但它们可以通过定义明确的薄 channel 进行通信。

关于c++ - Qt : Background thread refreshing UI thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2376835/

相关文章:

c++ - 捕获的变量隐藏了 lambda 中传递的变量。如何取消隐藏?

c++ - 从 vector C++ 中的元素中减去值

java - 如何在sbt项目中使用jnaerator

c++ - 如何定义声明的函数 - 具有未命名模板参数的模板结构成员?

c++ - 在QFileSystemModel中找到第n个文件/文件夹

Qt 事件循环和单元测试?

c++ - Dijkstra 算法实现 - 代码不适用于更大的输入

python - 将 QLineEdit 的 "enter"事件链接到插槽?

c++ - 不明白为什么我不能在 QMainWindow 子类中调用 setCentralWidget

qt - 桌面程序的“传统 Qt”或 'Qt Quick'?