问题
Qt有一个比较让人困扰的问题:不允许在子线程中对ui对象进行操作,否则会导致程序崩溃或者出现一些诡异的问题。解决这个问题的方法大致有两个:
- 通过信号槽连接,大体思路:当子线程中需要对ui对象进行操作时,发出一个信号,在与之连接的槽中处理ui操作。信号和槽的连接方式必须是
BlockingQueuedConnection
或QueuedConnection
的连接方式连接。 - 通过自定义event,在子线程中通过
QCoreApplication::postEvent
发出自定义的event,在对应的ui对象中重写customevent中处理自定义的event
GuiThreadRun类
上述这两种方式都可以解决问题,但不够优雅,借助c++11一些新特征,这里设计了一个类,可以以比较优雅的方式处理此类问题,类的定义如下:
#pragma once
#include <mutex>
#include <memory>
#include <thread>
#include <future>
#include <functional>
#include <QObject>
#include <QThread>
#include <QCoreApplication>
/*!
* \brief 用于将函数放在Qt的GUI线程中调用,通常用于需要在子线程中
* 操作UI对象的操作,可以调用普通函数、类成员函数、lambada表达式等
* 任何形式的函数。
* 使用前需在GUI线程调用一下GuiThreadRun::inst()后才能正常使用。
* 使用方法如下:
* 1. 普通函数 GuiThreadRun::excute(func,...) //...表示函数的参数
* 2. 类成员函数 GuiThreadRun::excute(&ClassName::func,classobj pointer,...)
*
* \author ICOODE
* \date 2021/07/19
*/
class GuiThreadRun : public QObject {
Q_OBJECT
public:
static GuiThreadRun *inst() {
static GuiThreadRun *s_this = new GuiThreadRun();
return s_this;
}
/**
* @brief 在gui线程中执行指定函数
* @param f 要执行函数的指针
* @param args 要执行函数的参数
* @return 同执行函数的返回类型一致
*/
template<typename F, typename... Args>
static auto excute(F &&f, Args&&... args)
-> typename std