如何在 C++ 端获取有效的 QQuickItem 实例
Posted
技术标签:
【中文标题】如何在 C++ 端获取有效的 QQuickItem 实例【英文标题】:How to get a valid instance of a QQuickItem on C++ side 【发布时间】:2016-10-21 13:46:34 【问题描述】:好的。我已经搜索了很多,但还没有一个好的解决方案。我是Qt
的新手。我有一堂课是QQuickItem
,就像这样,
class MyQuickItemClass : public QQuickItem
Q_OBJECT
SetInfo(SomeCppClass object)
;
我在我的main.cpp
中创建了一个qmlRegisterType
,以便像这样在qml
一侧注册它,
qmlRegisterType("MyQuickItemClass", 1, 0, "MyQuickItemClass");
到这里为止一切都很好。但是 -> 我想在 MyQuickItemClass 中设置一个对象实例和一些属性,其中还有一些 C++ 逻辑,然后将MyQuickItemClass
对象传递给qml
。或者,从 Qml 获取 MyQuickItemClass
的有效实例。 如何在main.cpp
的 C++ 端从 QML
获取 vlid 实例 MyQuickItemClass
对象实例?
我尝试通过链接here 进行以下学习。但是这种技术会创建两个独立的 MyQuickItemClass
对象。一个来自QML
,一个来自c++
。因此对我不起作用。
以下是我经过大量搜索后尝试执行此操作的方式。
int main(int argc, char *argv[])
qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");
QQmlApplicationEngine engine;
SomeCppClass someCppClassObject;
someCppClassObject.updateSomething();
MyQuickItemClass myquickItemObject;
myquickItemObject.SetInfo(someCppClassObject);
engine.rootContext()->setContextProperty("myquickItemObject", &myquickItemObject);
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
return app.exec();
但是,执行上述操作会使MyQuickItemClass
的构造函数被调用两次。当我创建一个对象时,一次来自cpp
,一次来自qml
。通过在MyQuickItemClass
的构造函数中放置一个断点来验证这一点。结果,当程序运行时,我设置的someCppClassObject
在MyQuickItemClass
内为空。因为 qml 已经对MyQuickItemClass
进行了最终调用来实例化,因此忽略了我在main.cpp
中创建的MyQuickItemClass
对象。
这是我的qml
代码MyQuickItemClass
:
import QtQuick 2.5
import MyQuickItemClass 1.0
ParentContainerItem
id: parentItem
color: "black"
MyQuickItemClass
id: myQuickItemID
visible: true
objectName: "myQuickItem"
property bool someProperty1: false
property bool someProperty2: true
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
//Other qml components
这是需要将其对象设置为MyQuickItemClass
的C++类。
SomeCppClass
//Pure C++ class. No Qt
请注意,我需要保留从QQuickItem
派生的MyQuickItemClass
。请建议...
【问题讨论】:
您遇到什么错误?实例如何“无效”?MyQuickItemClass
的构造函数被调用了两次。当我创建一个对象时,一次来自cpp
,一次来自qml
。通过在MyQuickItemClass
的构造函数中放置一个断点来验证这一点。结果,当程序运行时,我设置的someCppClassObject
在MyQuickItemClass
内为空。因为qml
最后调用MyQuickItemClass
进行实例化,因此忽略了我在main.cpp
中创建的MyQuickItemClass
对象
您也应该将错误添加到问题中。所以发现这个问题的人不必为此通读 cmets。
好的。现在将错误添加到问题中
向我们展示 main.qml
【参考方案1】:
通常最好避免访问 QML 实例化对象 from outside
,因为大多数访问方法会生成从 C++ 到 QML 的依赖关系,从而限制了 QML 树的完成方式。
例如要求某些对象在某个时间点存在,具有特定的objectName
值等。
最好通过在暴露的 C++ 对象/API 上调用方法从 QML 端“注册”对象,或者让 QML 在其自己的 C++ 代码中实例化对象注册自己。
后者显然本质上是自动的,即这样的类的每个实例都会这样做,而前者则让 QML 代码自行决定它想知道哪个创建的实例。
【讨论】:
没有任何方法可以从 qml 对象树中获取MyQuickItemClass
的有效实例并方便自己调用方法 SetInfo
吗?奇怪的 !!我以为这会很简单
有,只需使用QObject::findChild()
搜索给定对象名称的对象,但如果有更简洁的方法,为什么要这样做呢?【参考方案2】:
根据here 讨论中的建议执行以下操作可解决问题并获得 QuickItem qml 文件的有效对象
QQuickItem *myItem = engine.rootObjects()[0]->findChild<QQuickItem *>("myQuickItem");
【讨论】:
以上是关于如何在 C++ 端获取有效的 QQuickItem 实例的主要内容,如果未能解决你的问题,请参考以下文章
如何创建 QQuickItem 的单独副本并将其呈现在不同的窗口上
如何将 X 和 Y 转换值应用于 C++ 端的 QQuickItem
如何正确使用 QQuickItem::stackBefore() 重新排序 GridLayout 中的项目?