gpt4 book ai didi

qt - 为什么由 C++ 动态生成的 QML 项目不知道其他预先存在的项目?

转载 作者:行者123 更新时间:2023-12-03 03:45:43 25 4
gpt4 key购买 nike

我有一个QQuickView,它显示一个QML文件,该文件本身由多个QML项(在单独的文件中)组成。我想使用 C++ 代码动态添加项目。动态添加的项目应随父项调整大小,即 widthheight 属性引用父项。

例如,我在 QML 中的目标项目如下所示:

// 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();

这里出现错误(在应用程序输出 View 中):

DynamicItem.qml:4: ReferenceError: fillMeWithItemsContainer is not defined

quickView 应该知道 fillMeWithItemsContainer 的存在,因为它之前已经创建过。但是,fillMeWithItemsContainer 还不是 dynamicallyLoadedObject 的父级,这可能就是问题所在。

所以我通过

找到目标项目
QQuickItem *targetItem = quickView->rootObject()->findChild<QQuickItem*>("fillMeWithItemsContainer");

并重新设置先前创建的对象的父级

dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem ));

注意:我之前尝试过dynamicallyLoadedObject->setParent(),但这似乎是一种不同类型的父级(QObject 与父属性)。

但是,dynamicallyLoadedObject 的宽度和高度属性设置为 0(我认为是由于引用错误)并且不会更改。即使我以编程方式再次设置它们

dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");

没有任何改变。

如果我直接在 QML 中定义 DynamicItem,它会起作用:

Grid {
id: fillMeWithItemsContainer
objectName: "fillMeWithItemsContainer"

DynamicItem {}
}

如何确保动态添加的项目可以访问之前已在 QML View 中的项目?或者:我做错了什么?

最佳答案

dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;");
dynamicallyLoadedObject->setProperty("width", "height * 4/3");

这实际上不会在属性上设置 JavaScript 绑定(bind)。相反,它会尝试分配例如将字符串 "fillMeWithItemsContainer.height;" 添加到属性中,这将失败,因为该属性的类型为 int,而不是 QString 类型。实际上,在 C++ 中不可能将绑定(bind)分配给属性(有一些异常(exception),例如 QQmlBinding)。

dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem ));

正如 Sergei 提到的,您需要调用 QQuickItem::setParentItem 而不是设置 parent 属性。这也比一般基于字符串的 setProperty API 更加类型安全。如果没有父项,QQuickItem 将不可见。重新设置父级只会更改父项,这会影响布局和其他一些事情。它不会改变对象的上下文。上下文定义哪些对象/ID 在范围内。创建项目后,上下文无法更改。即使更改父对象会更改上下文,也为时已晚 - 对象已创建,并且仅在创建阶段查找 ID/对象。

解决方案是将正确的上下文传递给QQmlComponent::create(),它实际上有一个可选参数。您需要在 fillMeWithItemsContainer 的上下文中创建项目,因此您需要获取指向它的指针(您已经使用 findChild 做到了这一点),然后检索其上下文,其中可以通过 QQmlEngine::contextForObject() 实现。这应该足以让您弄清楚如何使其发挥作用。

不过我同意 Sergei 的观点,你应该更喜欢在 JavaScript 中动态创建对象。从 C++ 中更改 QML 是一种分层违规,您永远不应该从 C++ 访问 QML,只有相反,才能更好地分离 UI 和程序逻辑。

关于qt - 为什么由 C++ 动态生成的 QML 项目不知道其他预先存在的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20244063/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com