如何从另一个线程的 cpp 代码同步调用 qml 信号处理程序?

Posted

技术标签:

【中文标题】如何从另一个线程的 cpp 代码同步调用 qml 信号处理程序?【英文标题】:How to call qml signal handler synchronously from cpp code from another thread? 【发布时间】:2015-02-03 11:37:55 【问题描述】:

我知道通常你不会按照我的要求去做。我知道这两层应该是分开的,通过信号/槽机制连接,如果我们处理线程,这可能是异步的。

明白这一点,我仍然需要从 SG 线程同步调用 qml 信号处理程序。 Qml 对象存在于 GUI 线程中,因此从 SG 线程(特别是来自updatePaintNode() 方法)发出信号会导致异步事件。

我已阅读文档,并且从另一个线程的 cpp 同步调用 qml 函数没有问题。例如:

QMetaObject::invokeMethod(this, "myNiceQmlFunction", Qt::DirectConnection);

但是想象一下:

//some.cpp

signal void callQmlHandler();

//some.qml
MyObject 
    onCallQmlHandler: 
        // do something right now
    

我不知道如何通过QMetaObject::invokeMethod同步调用onCallQmlHandler。 我没有从代码创建 qml 对象,此时在 cpp 中我无法访问 qml 组件来查找它的子组件,在那里按名称找到 MyObject 并调用它的处理程序(如果可能的话)。无论如何,这不是一个漂亮的方法。

我试图在 QMetaObject 方法中找到信号处理程序,但它不存在。它也不在属性列表中(我检查以防万一,因为信号处理程序的语法类似于属性的语法)

有谁知道我是否错过了通过QMetaObject::invokeMethod 调用信号处理程序的正确语法,或者根本不可能?有什么想法吗?

【问题讨论】:

你检查Connections类型了吗?如前所述,它“可以接收来自其指定目标的任何信号。” 如果invokeMethod(this, "myNiceQmlFunction", ...);是一个C++语句,而this是一个C++对象,那么myNiceQmlFunction怎么能在QML上呢? @Smasho
this 的类型是使用“qmlRegisterType”为 qml 注册的,所以它可以非常简单。我只是在“Type”对象内的 qml“function myNiceQmlFunction() ”中声明。
@BaCaRoZzo 你能澄清一下吗?我不明白 qml Connections 类型如何帮助我从 c++ 调用处理程序。 在您的场景中有一个 c++ 信号并且处理程序在 QML 中。这就是我看到的代码。正如@Smasho 的回答所解释的那样,这是Connections 解决的一个用例。顺便说一句,跨线程的信号槽总是QueuedConnectioned。 【参考方案1】:

您可以使用其上下文将 C++ 对象传递给 QML。

qmlviewer.rootContext()->setContextProperty("backend", backend);

QML 方面:

Connections 
    target: backend
    onCallQmlHandler: 
        // do something right now
    

当您从后端对象发出callQmlHandler 时,您会执行处理程序。 但是Connections 对象可能会创建排队连接,因此您可以实现自己的DirectConnections。在this 帖子的末尾,您有一个实现。

但是 QML 是由 QML 引擎执行的,我认为该引擎旨在由单线程运行,因此除非您真的知道自己在做什么,否则您可能会遇到更大的问题!

【讨论】:

以上是关于如何从另一个线程的 cpp 代码同步调用 qml 信号处理程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个 QML 文件调用 QML 文件中定义的 Javascript 函数?

如何从另一个 QML 访问和控制 ListModel 的内容

如何从另一个 Qml 的 Qml 中的属性中获取值?

从另一个同步方法调用同步方法是不是安全?

QML , 如何从另一个 qml 访问元素

如何使用线程从另一个类调用不同的函数