c-异步调用插槽,而无需使用清晰的代码行连接到插槽

我遇到了非常怪异的错误-QAction :: trigger导致出现阻塞对话框,这导致我的服务器调用了触发卡住(例如,直到对话框关闭后才能处理套接字信号).

我想出了一种解决方法.我使用Qt :: QueuedConnection将信号void triggerWorkaround()连接到插槽QAction :: trigger,然后发出它:

QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);

但这是三行令人困惑的代码.有没有混淆的方法可以做到这一点?我发现QMetaObject::invokeMethod,但是坦率地说,那比我当前的解决方案混乱了10倍.另外,我也不想将方法名称用作字符串!

解决方法:

您可以将其分成一个函数QueuedInvoke,如下所示:

//overload for methods/slots
//the slot gets invoked in the thread where the QObject lives
template <typename Object, typename T>
void QueuedInvoke(Object* object, T (Object::* f)()){
    QObject signalSource;
    QObject::connect(&signalSource, &QObject::destroyed,
                     object, f, Qt::QueuedConnection);
}
//overload for functors
//the functor gets invoked in the thread where the contextObject lives
//or in the current thread if no contextObject is provided
template <typename Func>
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){
    QObject signalSource;
    QObject::connect(&signalSource, &QObject::destroyed, 
                     contextObject, std::forward<Func>(f), Qt::QueuedConnection);
}

这将利用从临时QObject发出的destroy()信号将排队的事件发布到事件循环中.当事件循环处理该事件时,实际上会调用插槽/功能键.

因此,您可以像这样使用上面的函数,而不是您发布的3行:

QueuedInvoke(targetAction_.data(), &QAction::trigger);

我的答案基于关于在给定QThread中执行函子的this great answer.您可以参考它以获取更多详细信息.

上一篇:deepin下安装Qt5&以及部分问题解决


下一篇:linux-嵌入Qt5的触摸屏不起作用