Qt 为什么a是由C++;生成的QML项不知道其他预先存在的项?
我有一个Qt 为什么a是由C++;生成的QML项不知道其他预先存在的项?,qt,qml,qtquick2,Qt,Qml,Qtquick2,我有一个QQuickView,它显示一个QML文件,该文件本身由几个QML项(在单独的文件中)组成。我想用C++代码动态添加项。动态添加的项应与父项一起调整大小,即宽度和高度属性引用父项 例如,QML中的目标项如下所示: // TargetContainer.qml Grid { id: fillMeWithItemsContainer objectName: "fillMeWithItemsContainer" } // DynamicItem.qml Rectangle
QQuickView
,它显示一个QML文件,该文件本身由几个QML项(在单独的文件中)组成。我想用C++代码动态添加项。动态添加的项应与父项一起调整大小,即宽度
和高度
属性引用父项
例如,QML中的目标项如下所示:
// TargetContainer.qml
Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"
}
// DynamicItem.qml
Rectangle {
color: "white"
height: fillMeWithItemsContainer.height
width: height * 4/3
}
我要动态(可能多次)添加的项目如下所示:
// TargetContainer.qml
Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"
}
// DynamicItem.qml
Rectangle {
color: "white"
height: fillMeWithItemsContainer.height
width: height * 4/3
}
请注意,矩形在高度方面引用了它要驻留的容器。
quickView
填充了TargetContainer
:
QQuickView *quickView = new QQuickView();
quickView->setSource(QUrl("qrc:/foo/bar/TargetContainer.qml"));
所以我加载一个组件
QQmlComponent dynamicallyLoadedComponent(
quickView->engine(),
QUrl("qrc:/foo/bar/DynamicItem.qml")
);
我从中创建了一个对象
QObject *dynamicallyLoadedObject = dynamicallyLoadedComponent.create();
这里我得到一个错误(在应用程序输出视图中):
quickView
应该知道存在fillMeWithItemsContainer
,因为它以前已经创建过。但是,fillMeWithItemsContainer
不是dynamicallyLoadedObject
的父对象,这可能就是问题所在
因此,我通过
QQuickItem *targetItem = quickView->rootObject()->findChild<QQuickItem*>("fillMeWithItemsContainer");
没有什么变化
如果我直接在QML中定义DynamicItem,它就会工作:
Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"
DynamicItem {}
}
如何确保动态添加的项可以访问以前已在QML视图中的项?或者:我做错了什么?我相信,QML引擎将
DynamicItem
实例视为非图形项目,因为它被强制转换为QObject*
。因此,它不会被渲染。它必须至少是QQuickItem*
才能呈现
我相信您在使用setParent()
时也会遇到同样的问题,因为parent
属性引用了parentQQuickItem
并且可能与QObject
parent不同
两个问题:
parent
而不是绝对的fillMeWithItemsContainer
dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");
这实际上不会在属性上设置JavaScript绑定。相反,它将尝试将字符串“fillMeWithItemsContainer.height;”
分配给属性,这将失败,因为属性的类型为int
,而不是QString
类型。
从C++中分配绑定实际上是不可能的(除了一些例外,如代码> QQML绑定< /代码>)。
dynamicallyLoadedObject->setProperty(“父”,QVariant::fromValue(targetItem));
正如Sergei提到的,您需要调用QQuickItem::setParentItem
,而不是设置parent
属性。这也比一般的基于字符串的setProperty
API更加类型安全。如果没有父项,QQuickItem将不可见。
重新分页只会更改父项,这将影响布局和其他一些事情。它不会改变对象的上下文。上下文定义作用域中的对象/ID。创建项目后,无法更改上下文。即使更改父对象会更改上下文,也为时已晚-对象已创建,ID/对象仅在创建阶段查找
解决方案是将正确的上下文传递给QQmlComponent::create()
,它实际上有一个可选参数。您需要在fillMeWithItemsContainer
的上下文中创建项目,因此您需要获取指向它的指针(您已经在findChild
中这样做了),然后检索它的上下文,这可以通过QQmlEngine::contextForObject()
实现。这应该给你足够的时间去弄清楚如何让它工作
不过,我同意Sergei的观点,您应该更喜欢用JavaScript动态创建对象。从C++中改变QML是一种分层违反,你不应该从C++访问QML,而只能通过另一种方式来在UI和程序逻辑之间有更好的分离。这里的铸造是不相关的——qqMListC::CREATE()创建正确类型的对象,在这种情况下是QQuiQuin的一个子类。强制转换该指针不会以任何方式改变其类型,它将保持为QQuickItem。@tmcguire感谢您的更正。在这种情况下,将DynamicObject实例指针转换为QObject是不相关的。(我搞砸了上下文属性。)
dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");
dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem ));