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
。
这会强制执行以下顺序:
idRectParent
在 QQmlObjectCreator::createInstance()
中构造,子级在函数退出 idRectParent
之前通过对 QQmlObjectCreator::createInstance()
的递归调用开始构造。
idRectChild1
完成 QQmlObjectCreator::createInstance()
并被推入 componentAttached 堆栈。
idRectChild2
完成 QQmlObjectCreator::createInstance()
并被推入 componentAttached 堆栈。
idRectParent
完成 QQmlObjectCreator::createInstance()
并被推入 componentAttached 堆栈。
QQmlComponent::completeCreate()
调用 QQmlObjectCreator::finalize()
并且 componentAttached 堆栈被清空并为每个项目发出 onCompleted
:
idRectParent
从 componentAttached 堆栈中弹出并发出 onCompleted
信号。
idRectChild2
从 componentAttached 堆栈中弹出并发出 onCompleted
信号。
idRectChild1
从 componentAttached 堆栈中弹出并发出 onCompleted
信号。
无论项目的层次结构有多深,都会保持此顺序:父级优先,然后是子级,声明顺序相反。
【讨论】:
以上是关于QML 文件中有很多项目的 Component.onCompleted 的顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章