对于项目,我需要在运行时从C创建QML组件 .
我的一般架构如下:
PROJECT1:
-
Engine.h
-
Engine.cpp
-
CustObject.h
-
CustObject.cpp
-
Plugin.h
-
Plugin.cpp
-
Dummy.qml
项目2:
-
main.cpp
-
main.qml
我想要做的是将Engine.cpp实例化为QML对象(可能因为我在Plugin类中注册它并使其可用于Project2)然后从Engine创建动态CustObject实例(它们也被Project2注册使用) . 最后我想要,如果我写:
ApplicationWindow{
id: window
visible: true
Engine{
id: eng1
CustObject{
id: custObj1
}
}
}
这与编写类似的内容相同
ApplicationWindow {
id: window
visible: true
Button {
text: "add new child"
onClicked: {
console.log("QML: Number children before", eng1.children.length);
eng1.addNewChildren();
console.log("QML: Number children after", eng1.children.length);
}
}
Engine{
id: eng1
onChildrenChanged: console.log("Changed")
}
}
我应该看到,孩子的数量会增加,并且应该启动从eng1开始的onChildrenChanged .
问题是孩子的数量都没有增加,也没有启动onChildrenChanged信号 .
我还有另外一个问题,为了在我的情况下将子项添加到父项,eng1,我使用了QQMLComponent类的函数QQmlComponent(QQmlEngine * engine,const QUrl&url,QObject * parent = 0) . 但我找不到将CustObject类转换为QUrl的方法,因为它不是.qml文件 .
因此,我首先尝试添加一个名为Dummy.qml的虚拟qml对象,而不是CustObject对象 . Dummy.qml看起来像这样:
import QtQuick 2.0
Item {
property int nb: 1
}
我的Engine类的代码如下所示:
Engine.h:
#ifndef ENGINE_H
#define ENGINE_H
#include <QQuickItem>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlContext>
class Engine : public QQuickItem{
Q_OBJECT
public:
explicit Engine(QQuickItem* parent = 0);
virtual ~Engine();
Q_INVOKABLE QObject* addNewChildren();
};
#endif // ENGINE_H
Engine.cpp:
#include "Engine.h"
Engine::Engine(QQuickItem* parent) :
QQuickItem(parent)
{
}
Engine::~Engine(){ }
QObject* Engine::addNewChildren(){
qDebug() << "CPP: Number children before " << this->children().size();
QObject* parentEntity = this;
QQmlComponent* childrenEntity;
QQmlComponent component(qmlEngine(this), QUrl("qrc:///src/Dummy.qml"));
QQuickItem *childrenItem = qobject_cast<QQuickItem*>(component.create());
QQmlEngine::setObjectOwnership(childrenItem, QQmlEngine::CppOwnership);
childrenItem->setParent(parentEntity);
childrenItem->setProperty("nb", 2);
qDebug() << "CPP: Number children after" << this->children().size();
//qDebug() << "Property value:" << QQmlProperty::read(childrenItem, "nb").toInt();
return childrenItem;
}
但是当我运行main.qml时我的输出如下:
qml: QML: Number children before 0
CPP: Number children before 0
CPP: Number children after 1
qml: QML: Number children after 0
由于以下错误,我评论了对应于QQmlProperty :: read的行:“嵌套名称说明符qDebug中使用的不完整类型'QQmlProperty'()<<”属性值:“<< QQmlProperty :: read(childrenItem,”nb“ ).toInt();” ^
因此,我有以下问题:
-
为什么从qml看不到儿童增加的数量(但是从cpp可见)?
-
为什么onChildrenChanged没有从qml启动?
-
如何添加动态CustObject类(从Project2的角度看它是一个qml对象,因为它已经注册)而不是Dummy.qml?
-
如何在C创建后立即读取动态添加对象的属性(即如何使用QQMlProperty :: read)?
非常感谢你提供给我的任何帮助!
1 回答
QML不使用
QObject::children()
,而是使用QQuickItem::childItems() . 是的,没错,有两个不同的孩子列表,一个来自QObject
,另一个来自QQuickItem
. 两者都有不同的用途:QObject中的一个主要用于内存管理(当父项被删除时,子项被删除),而QQuickItem中的一个用于'visual hierachy',例如孩子们被吸引到他们的父母之上 . 有关详细信息,请参见the docs .因为
onChildrenChanged
仅在QQuickItem::childItems()
更改时发出,但它不会发生 . 除了setParent()
之外,请致电setParentItem()
以解决此问题 .只需自己创建对象并设置
parent
和parentItem
即可 . 这里没有必要使用QQmlComponent
.调用
QQuickItem::childItems()
应该可以解决问题,无需读取属性 . FWIW,代码中可能缺少#include <QQmlProperty>
,但是没有用 .