我有一个QQuickView显示QML文件,它本身由几个QML项目(在单独的文件中)组成.我想使用C++代码动态添加Items.动态添加的项目应与父一个调整大小,即width和height属性参考的父.
例如,我在QML中的目标Item看起来像这样:
// TargetContainer.qml
Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"
}
Run Code Online (Sandbox Code Playgroud)
我想动态添加的项目(可能是多次)看起来像这样:
// DynamicItem.qml
Rectangle {
color: "white"
height: fillMeWithItemsContainer.height
width: height * 4/3
}
Run Code Online (Sandbox Code Playgroud)
请注意,矩形引用了有关高度的容器.
quickView填充有TargetContainer:
QQuickView *quickView = new QQuickView();
quickView->setSource(QUrl("qrc:/foo/bar/TargetContainer.qml"));
Run Code Online (Sandbox Code Playgroud)
所以我加载了一个组件
QQmlComponent dynamicallyLoadedComponent(
quickView->engine(),
QUrl("qrc:/foo/bar/DynamicItem.qml")
);
Run Code Online (Sandbox Code Playgroud)
我创建了一个Object.
QObject *dynamicallyLoadedObject = dynamicallyLoadedComponent.create();
Run Code Online (Sandbox Code Playgroud)
这里我得到一个错误(在应用程序输出视图中):
DynamicItem.qml:4: ReferenceError: fillMeWithItemsContainer is not defined
Run Code Online (Sandbox Code Playgroud)
quickView应该知道fillMeWithItemsContainer它的存在,因为它之前已经被创造过了.但是,fillMeWithItemsContainer不是dynamicallyLoadedObject(还)的父母,这可能是问题所在.
所以我找到了目标项目
QQuickItem *targetItem = quickView->rootObject()->findChild<QQuickItem*>("fillMeWithItemsContainer");
Run Code Online (Sandbox Code Playgroud)
并重新显示以前创建的对象
dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem ));
Run Code Online (Sandbox Code Playgroud)
注意:我dynamicallyLoadedObject->setParent()之前尝试过,但这似乎是一种不同的父类(QObject与父属性相对).
但是,宽度和高度属性dynamicallyLoadedObject设置为0(因为参考错误,我假设)并且不会更改.即使我以编程方式再次设置它们
dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");
Run Code Online (Sandbox Code Playgroud)
没有什么变化.
如果我直接在QML中定义DynamicItem,它可以工作:
Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"
DynamicItem {}
}
Run Code Online (Sandbox Code Playgroud)
如何确保动态添加的项目可以访问以前在QML视图中的项目?或者:我做错了什么?
dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");
Run Code Online (Sandbox Code Playgroud)
这实际上不会在属性上设置JavaScript绑定.相反,它会尝试将字符串分配给"fillMeWithItemsContainer.height;"属性,这将失败,因为属性是类型int,而不是类型QString.在C++中实际上不可能为属性分配绑定(有一些例外QQmlBinding).
dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem ));
Run Code Online (Sandbox Code Playgroud)
正如谢尔盖所说,你需要打电话QQuickItem::setParentItem而不是设置parent财产.这也比一般的基于字符串的setPropertyAPI 更安全.如果没有父项,则QQuickItem将不可见.重新显示只会更改父项,这将影响布局和其他一些事项.它不会改变对象的上下文.上下文定义了范围内的哪些对象/ ID.创建项目后,无法更改上下文.即使更改父级将更改上下文,也为时已晚 - 已创建对象,并且仅在创建阶段查找ID /对象.
解决方案是将正确的上下文传递给QQmlComponent::create()实际具有可选参数的上下文.你需要在上下文中创建你的项目fillMeWithItemsContainer,所以你需要获得一个指向它的指针(你已经这样做了findChild),然后检索它的上下文,这是可能的QQmlEngine::contextForObject().这应该足以让你弄明白如何让它发挥作用.
我同意谢尔盖,你应该更喜欢用JavaScript动态创建对象.在C++中更改QML是一种分层违规,你永远不应该从C++访问QML,只是相反,才能在UI和程序逻辑之间实现更好的分离.
| 归档时间: |
|
| 查看次数: |
4728 次 |
| 最近记录: |