QML 文件中有很多项目的 Component.onCompleted 的顺序是啥?

Posted

技术标签:

【中文标题】QML 文件中有很多项目的 Component.onCompleted 的顺序是啥?【英文标题】:What is the order of Component.onCompleted in a QML file with many items?QML 文件中有很多项目的 Component.onCompleted 的顺序是什么? 【发布时间】:2014-07-04 15:06:26 【问题描述】:

例如,考虑下面的代码:

Rectangle 
    id: idRectParent

    Rectangle 
        id: idRectChild1
        component.onCompleted: 
            console.log("Iam Child 1")
        
    

    Rectangle 
        id: idRectChild2
        component.onCompleted: 
            console.log("Iam Child 2")
        
    

    component.onCompleted : 
        console.log("Iam parent Rect")
    

如果我在 qmlscene 中运行它,我会得到下面的输出(我已经尝试了将近 50 次)。

Iam parent Rect
Iam Child 2
Iam Child 1

为什么是上面的顺序输出,而不是:

Iam parent Rect
Iam Child 1
Iam Child 2

Iam Child 1
Iam Child 2
Iam parent Rect

或任何其他组合。

【问题讨论】:

【参考方案1】:

订单未定义:

组件“启动”完成后发出。这可以用来 在启动时执行脚本代码,一旦完整的 QML 环境已经完成 成立。

相应的处理程序是 onCompleted。有可能 在任何对象上声明。运行 onCompleted 处理程序的顺序 未定义。

http://qt-project.org/doc/qt-5/qml-qtqml-component.html#completed-signal

【讨论】:

如果 MainPage.qml 由 main.qml 通过属性绑定 - mainPage: MainPage 加载,来自 main.qml 的所有 onCompleted 处理程序会在所有 MainPage.qml 处理程序之前执行,还是未定义? 【参考方案2】:

顺序是未定义的,但它是有意义的(并且可以根据经验观察),当 OnCompleted 方法被调用时,它的所有子项都被实例化并安全访问(并且属性已初始化),即使 OnCompleted 事件因为这些孩子还没有被调用。

【讨论】:

这不是真的,当父对象的onCompleted 被调用时,OP 证明了这一点,即使他的孩子还没有。 如果你不指定更好,你说的将与我写的兼容。根据经验观察,我的猜想是,当父母启动其onCompleted 而孩子还没有启动时,他们仍然可以安全访问 @Venemo 我编辑了答案,阐明了我想表达的概念。对此还有什么反馈吗?你真的没看我写的吗? 这比前面的写法清楚多了。谢谢。【参考方案3】:

顺序由 C++ 类决定,对于简单声明,从 Qt 4.8 到 5.15 的顺序保持不变。

该示例描述了一个包含项目的 QML 组件。 C++ 调用按以下顺序发生:

    调用QQmlComponent::beginCreate() 来创建组件。 调用QQmlObjectCreator::createInstance() 来创建组件中的每个项目。 QQmlObjectCreator::createInstance() 为在项目中声明的每个子项递归调用。 如果子项没有子项,则将其添加到 componentAttached 堆栈以供以后完成。 通过各自的QQmlObjectCreator::createInstance() 调用创建所有子级后,父级的QQmlObjectCreator::createInstance() 继续执行,并且父级将添加到componentAttached 堆栈以供稍后完成。 QQmlComponent::beginCreate() 调用退出。 调用QQmlComponent::completeCreate()完成组件。 componentAttached 堆栈被清空并在每个项目从堆栈中弹出时发出onCompleted

这会强制执行以下顺序:

    idRectParentQQmlObjectCreator::createInstance() 中构造,子级在函数退出 idRectParent 之前通过对 QQmlObjectCreator::createInstance() 的递归调用开始构造。 idRectChild1 完成 QQmlObjectCreator::createInstance() 并被推入 componentAttached 堆栈。 idRectChild2 完成 QQmlObjectCreator::createInstance() 并被推入 componentAttached 堆栈。 idRectParent 完成 QQmlObjectCreator::createInstance() 并被推入 componentAttached 堆栈。

QQmlComponent::completeCreate() 调用 QQmlObjectCreator::finalize() 并且 componentAttached 堆栈被清空并为每个项目发出 onCompleted

    idRectParentcomponentAttached 堆栈中弹出并发出 onCompleted 信号。 idRectChild2componentAttached 堆栈中弹出并发出 onCompleted 信号。 idRectChild1componentAttached 堆栈中弹出并发出 onCompleted 信号。

无论项目的层次结构有多深,都会保持此顺序:父级优先,然后是子级,声明顺序相反。

【讨论】:

以上是关于QML 文件中有很多项目的 Component.onCompleted 的顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 更改 QML Listview 委托

如何从另一个 Qml 的 Qml 中的属性中获取值?

无法锚定到不是父项或同级 QML QtQuick 的项目

QML-开发中遇到的错误收集

如何在 QML 的列表中直接声明项目?

在 QML 中截取特定项目的屏幕截图的方法是啥?