Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt 为什么a是由C++;生成的QML项不知道其他预先存在的项?_Qt_Qml_Qtquick2 - Fatal编程技术网

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
属性引用了parent
QQuickItem
并且可能与
QObject
parent不同

两个问题:

  • 为什么不在JS中创建动态对象
  • 是否可以使用相对的
    parent
    而不是绝对的
    fillMeWithItemsContainer
  • p、 我假设您理解这是一种非常不规则的使用QML的方式,并且有充分的理由使用这种黑客方法

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