如何在 Qt 主线程中正确执行 GUI 操作? [英] How to properly execute GUI operations in Qt main thread?

查看:50
本文介绍了如何在 Qt 主线程中正确执行 GUI 操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由两个线程组成的简单程序:

I have a simple program that consists of two threads:

  1. Qt 操作的主 GUI 线程 QApplication::exec
  2. boost::asio::io_service
  3. 操作的 TCP 网络线程
  1. Main GUI thread operated by Qt QApplication::exec
  2. TCP network thread operated by boost::asio::io_service

TCP 事件,例如连接或接收数据会导致 GUI 发生变化.大多数情况下,这些是 QLabel 上的 setText 并隐藏各种小部件.目前,我在 TCP 客户端线程中执行这些操作,这似乎很不安全.

TCP events, such as connecting or receiving data cause changes in GUI. Most often, those are setText on QLabel and hiding various widgets. Currently, I am executing those actions in TCP client thread, which seems quite unsafe.

如何正确地将事件发布到 Qt 主线程?我正在寻找 boost::asio::io_service::strand::post 的 Qt 变体,它将事件发布到 boost::asio::io_service 事件循环.

How to post properly an event to Qt Main thread? I am looking for Qt variant of boost::asio::io_service::strand::post, which posts event to boost::asio::io_service event loop.

推荐答案

如果你不想让你的 TCP 类成为 QObject 另一个选择是使用 QMetaObject::invokeMethod() 函数.

If you do not want to make your TCP class a QObject another option is to use the QMetaObject::invokeMethod() function.

那么要求是您的目标类必须是一个 QObject 并且您必须调用在目标上定义的槽.

The requirement then is that your destination class must be a QObject and you must call a slot defined on the destination.

假设您的 QObject 定义如下:

Say your QObject is defined as follow:

class MyQObject : public QObject {
    Q_OBJECT
public: 
    MyObject() : QObject(nullptr) {}
public slots:
    void mySlotName(const QString& message) { ... }
};

然后您可以从您的 TCP 类调用该插槽.

Then you can call that slot from your TCP Class.

#include <QMetaObject>

void TCPClass::onSomeEvent() {
    MyQObject *myQObject = m_object;
    myMessage = QString("TCP event received.");
    QMetaObject::invokeMethod(myQObject
                               , "mySlotName"
                               , Qt::AutoConnection // Can also use any other except DirectConnection
                               , Q_ARG(QString, myMessage)); // And some more args if needed
}

如果您使用 Qt::DirectConnection 进行调用,则插槽将在 TCP 线程中执行,并且它可能/将会崩溃.

If you use Qt::DirectConnection for the invocation the slot will be executed in the TCP thread and it can/will crash.

由于 invokeMethod 函数是静态的,您可以从任何类调用它,并且该类不需要是 QObject.

Since invokeMethod function is static, you can call it from any class and that class does not need to be a QObject.

这篇关于如何在 Qt 主线程中正确执行 GUI 操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆