如何在 C++ 端获取 QQuickItem 的 C++ 对象实例 [重复]
Posted
技术标签:
【中文标题】如何在 C++ 端获取 QQuickItem 的 C++ 对象实例 [重复]【英文标题】:How to get a C++ object instance of a QQuickItem on C++ side [duplicate] 【发布时间】:2016-10-22 17:40:19 【问题描述】:我有QtApp
和一个纯 C++ 库。 C++ 库公开了一个名为MyCppLibApiClass
的简单类。 QtApp
有一个嵌入在main.qml
上的类。以下是课程:
class MyQuickItem : public QQuickItem
MyQuickItem();
按照qml
代码为quick item
:
import MyQuickItem 1.0
MyQuickItem
id: myQuickItemID
visible: true
objectName: "myQuickItem"
以下是我的main.cpp
,显示我加载了qml
项目:
qmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
return app.exec();
MyQuickItem
需要访问 MyCppLibApiClass
实例。 如何在main.cpp
中获得MyQuickItem
的有效实例? 我需要将MyCppLibApiClass
的对象设置为MyQuickItem
中的成员。我可以使用 setter 方法来做到这一点。但是,首先我需要获得MyQuickItem
的有效实例。那么如何在main.cpp
中访问MyQuickItem
?
编辑: 在问这个问题之前,我已经搜索了很多。我通读了这个link。另外,我发布的This 问题没有给我一个准确的答案。因此,更清楚地改写我的问题以尝试得到答案。感谢对此的建议..
【问题讨论】:
要将您的类公开给 QML,您应该至少从 QObject 派生它(如果这是可见项目,则从 QQuickItem 派生)。在另一种情况下,您可以将其包装到 QObject 中,然后使用qmlRegisterType
将其公开给 QML
正如您在我的问题中看到的,我已经从QQuickItem
派生了MyQuickItem
。现在,我应该如何访问MyQuickItem
在main.cpp
中的实例?
这是什么意思?如果您使用 qmlRegisterType
将您的类公开给 QML,则不应实例化它。它将被 QML 实例化。
我的问题是:如何访问 QML 在调用 qmlRegisterType
后创建的 MyQuickItem
实例。
啊..现在就知道了。只需将 objectName
分配给 QML 项目,QQuickItem *myItem = engine.rootObjects()[0]->findChild<QQuickItem *>("myQuickItem");
也是如此
【参考方案1】:
如果您有一个库对象的单个实例,您可以通过两种方式来处理它,具体取决于您需要什么样的访问权限:
将实例作为 MyQuickItem
类的静态成员,在创建 QML 应用程序之前在 main.cpp
中初始化它,然后您可以在 C++ 中从 MyQuickItem
内部访问它。
让实例继承 QObject
并将其公开为上下文属性,这样就可以从 QML 访问它。
如果它不是一个单例对象,你有两个动作:
从 C++ 创建 QML 对象,它会给你直接指向它的指针 使用QQmlApplicationEngine::rootObjects().at(0).findChild()
作为类型和对象名称在对象树中查找 QML 对象,如果找到,您将拥有指向该对象的指针
但是,正如您喜欢的问题的答案之一所暗示的那样,这并不是真正的推荐做法。可能有更好的方法来做到这一点,你不应该在 main.cpp 中设置 QML 对象属性,它应该在 MyQuickItem
的构造函数或公共接口中。
【讨论】:
感谢您对此的关注。我可以在接受纯 C++ 类的MyQuickItem
中公开setproperty
吗?您能否在 github 或其他地方提供一些参考项目?
您可以在 QML 中传递不透明的非 QObject 派生 C++ 类型作为参数并返回值,如果您 Q_DECLARE_METATYPE(YourType)
那就是如果您需要从 QML 执行此操作,则从 C++ 您可以完全访问对象的公共接口,你可以为所欲为。但同样,您做错了。现在可能不重要,但迟早会的。从长远来看,糟糕的设计总是很糟糕。
@NelsonP - 您的使用场景未知,因此我无法获得具体建议。但是,使用 C++ INSIDE MyQuickItem
中的库而不是 main.cpp 有什么问题?听起来这就是你应该做的。
我是 Qt 新手。在回答或询问任何其他信息之前,我必须先尝试这些建议。我会在尝试后回来。非常感谢您对此的关注。
如果您从 QML 调用并在那里传递参数,您只需要变体包装器。在 C++ 方面,你不需要那种糖。【参考方案2】:
在你的 main.cpp 中:
qmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem");
QQmlApplicationEngine engine;
MyQuickItem myItem;
engine.rootContext()->setContextProperty("myItem", &myItem);
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
现在您可以从 C++ 访问 myItem 并从 QML 访问相同的 myItem,只需将 QML 上下文的根级别上的属性“myItem”设置为对您的自定义对象的引用。
编辑
我在答案中添加了 qmlRegisterType 声明。
根据评论中的要求:
使用 qmlRegisterType() 用于在 QML 中注册特定类型,然后可以从 QML 创建/访问。
通过使用engine.rootContext()->setContextProperty("myItem", &myItem)
方法您实际上是在 C++ 中创建 myItem
并将 myItem
的所有权设置为 C++
由于 QML 旨在与 C++ 一起使用,因此可以简单地将 myItem
分配为 QML 中的属性,并且由于 QML 自动从父对象继承属性/对象,因此 myItem
在整个 QML 上下文中都可用。
这两个例子都没有经过测试,只是为了演示这个想法
main.qml 示例
import MyQuickItem 1.0
Item
Component.onCompleted
myItem.visible = true;
myItem.myCustomMethod();
C++ 类示例
class MyQuickItem : public QQuickItem
MyQuickItem();
public slots:
void myCustomMethod() /* do some C++ stuff here */
【讨论】:
我的答案实际上只是 ddriver 的答案,只是用代码写出来的,所以要更好地理解它,请参阅上面的 ddriver 的答案 感谢代码。我看到你没有做qmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem")
。如果我不这样做,那么 Qt 不允许我执行import MyQuickItem 1.0
。因此,完全禁止我在 main.qml
中声明 MyQuickItem
。 qmlRegisterType
不再需要了?您能否提供MyQuickItem
周围代码的qml
部分?以上是关于如何在 C++ 端获取 QQuickItem 的 C++ 对象实例 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何创建 QQuickItem 的单独副本并将其呈现在不同的窗口上
如何将 X 和 Y 转换值应用于 C++ 端的 QQuickItem
如何正确使用 QQuickItem::stackBefore() 重新排序 GridLayout 中的项目?