【发布时间】:2016-07-11 03:50:55
【问题描述】:
对于一个项目,我需要在运行时从 C++ 创建 QML 组件。
我的总体架构如下:
项目1:
- Engine.h
- Engine.cpp
- CustObject.h
- CustObject.cpp
- 插件.h
- 插件.cpp
- Dummy.qml
项目2:
- main.cpp
- main.qml
我想要做的是将 Engine.cpp 实例化为 QML 对象(可能是因为我在 Plugin 类中注册它并使其可用于 Project2),然后动态创建 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 的行:“嵌套名称说明符中使用的不完整类型 'QQmlProperty' qDebug()
因此我有以下问题:
- 为什么从 qml 看不到子项增量的数量(但从 cpp 可见)?
- 为什么 onChildrenChanged 没有从 qml 启动?
- 如何动态添加 CustObject 类(从 Project2 的角度来看,它作为 qml 对象可见,因为它已注册) 而不是 Dummy.qml?
- 如何在 C++ 中读取动态添加的对象的属性(即如何使用 QQMlProperty::read)?
非常感谢您能给我的任何帮助!
【问题讨论】:
-
这是一个私人信号,你不应该使用它。
-
感谢您的快速回复!那么当一个孩子被添加到我的引擎时,我应该使用什么信号来执行操作?你有什么想法,为什么我的 children 变量没有从 qt 的角度更新,而是从 c++ 更新是的?
-
Qt 的内部设计相当静态且不灵活,您实际上没有选择更改或利用它的选项。你可以覆盖它,但是谁知道你可能会破坏什么,总而言之,它并不漂亮。更好的策略是改变您的设计以解决 Qt 的限制。拥有自己的自定义函数来创建对象并发出自定义信号来通知。
-
谢谢,但是你告诉我 onChildrenChanged 不应该直接在任何 qml 代码中使用?孩子变量呢?它不是一个可靠的变量,可用于随时了解父母的子女人数吗? (在我的情况下,它不可靠,因为它不会从 qml 的角度改变)无论如何我会研究一个新的设计。我的想法是为 Engine 类保留一个 List
子类,并有一个关联的信号链接到这个列表。你认为这是个好主意吗?你对我的其他 3 个问题有什么想法吗? (1,3 和 4)