[英]How to analyse a “Binding loop”
我有一個帶有 C++ 模型和 QML 可視化的 Qt/QML 應用程序。
在運行時(啟動),我收到警告
QML 項目:檢測到屬性“xyz”的綁定循環
我在 QML 中沒有看到明顯的循環。 我可以啟用更多調試以了解此循環的來源嗎? 其他建議?
我通常通過在打印警告的 Qt 代碼中放置一個斷點來做到這一點。 為此,您需要有一個帶有調試符號的 Qt。
在 Qt 源中搜索“檢測到綁定循環”給了我QQmlAbstractBinding::printBindingLoopError() 。 在那里放置斷點通常會導致回溯,從而清楚地了解情況。
更新:David Edmundson 開發了一個小工具,可以在綁定循環上顯示僅限 QML 的回溯,請在此處查看他的博客。 引擎蓋下的功能與此處描述的完全相同,只是它很好地自動化並封裝在 Python 腳本中。
示例:
Rectangle {
id: parent
width: child.width + 1
height: child.height + 1
Rectangle {
id: child
anchors.fill: parent
}
}
回溯:
1 QQmlAbstractBinding::printBindingLoopError qqmlabstractbinding.cpp 178 0x7ffff6eb36da
2 QQmlBinding::update qqmlbinding.cpp 221 0x7ffff6eb9abe
3 QQmlBinding::update qqmlbinding_p.h 97 0x7ffff6eba354
4 QQmlBinding::expressionChanged qqmlbinding.cpp 260 0x7ffff6eb9e68
5 QQmlJavaScriptExpressionGuard_callback qqmljavascriptexpression.cpp 361 0x7ffff6eb223e
6 QQmlNotifier::emitNotify qqmlnotifier.cpp 94 0x7ffff6e9087a
7 QQmlData::signalEmitted qqmlengine.cpp 763 0x7ffff6e19a45
8 QMetaObject::activate qobject.cpp 3599 0x7ffff683655e
9 QMetaObject::activate qobject.cpp 3578 0x7ffff6836364
10 QQuickItem::widthChanged moc_qquickitem.cpp 1104 0x7ffff7a7ba49
11 QQuickItem::geometryChanged qquickitem.cpp 3533 0x7ffff7a6e9cd
12 QQuickItem::setSize qquickitem.cpp 6389 0x7ffff7a75f35
13 QQuickAnchorsPrivate::setItemSize qquickanchors.cpp 400 0x7ffff7a60d94
14 QQuickAnchorsPrivate::fillChanged qquickanchors.cpp 177 0x7ffff7a5fe0e
15 QQuickAnchorsPrivate::itemGeometryChanged qquickanchors.cpp 441 0x7ffff7a6106f
16 QQuickItem::geometryChanged qquickitem.cpp 3523 0x7ffff7a6e96c
17 QQuickItem::setWidth qquickitem.cpp 6091 0x7ffff7a74c1d
18 QQuickItem::qt_static_metacall moc_qquickitem.cpp 874 0x7ffff7a7b0dc
19 QQuickItem::qt_metacall moc_qquickitem.cpp 946 0x7ffff7a7b4d8
20 QQuickRectangle::qt_metacall moc_qquickrectangle_p.cpp 610 0x7ffff7c189c2
21 QMetaObject::metacall qmetaobject.cpp 296 0x7ffff680118b
22 QQmlPropertyPrivate::writeBinding qqmlproperty.cpp 1512 0x7ffff6e33ec3
23 QQmlBinding::update qqmlbinding.cpp 199 0x7ffff6eb992a
24 QQmlBinding::update qqmlbinding_p.h 97 0x7ffff6eba354
25 QQmlBinding::expressionChanged qqmlbinding.cpp 260 0x7ffff6eb9e68
26 QQmlJavaScriptExpressionGuard_callback qqmljavascriptexpression.cpp 361 0x7ffff6eb223e
27 QQmlNotifier::emitNotify qqmlnotifier.cpp 94 0x7ffff6e9087a
28 QQmlData::signalEmitted qqmlengine.cpp 763 0x7ffff6e19a45
29 QMetaObject::activate qobject.cpp 3599 0x7ffff683655e
30 QMetaObject::activate qobject.cpp 3578 0x7ffff6836364
31 QQuickItem::widthChanged moc_qquickitem.cpp 1104 0x7ffff7a7ba49
32 QQuickItem::geometryChanged qquickitem.cpp 3533 0x7ffff7a6e9cd
33 QQuickItem::setSize qquickitem.cpp 6389 0x7ffff7a75f35
34 QQuickAnchorsPrivate::setItemSize qquickanchors.cpp 400 0x7ffff7a60d94
35 QQuickAnchorsPrivate::fillChanged qquickanchors.cpp 177 0x7ffff7a5fe0e
36 QQuickAnchorsPrivate::update qquickanchors.cpp 431 0x7ffff7a60fc6
37 QQuickAnchorsPrivate::updateOnComplete qquickanchors.cpp 425 0x7ffff7a60f93
38 QQuickItem::componentComplete qquickitem.cpp 4593 0x7ffff7a70944
39 QQmlObjectCreator::finalize qqmlobjectcreator.cpp 1207 0x7ffff6ecab66
40 QQmlComponentPrivate::complete qqmlcomponent.cpp 928 0x7ffff6e38609
41 QQmlComponentPrivate::completeCreate qqmlcomponent.cpp 964 0x7ffff6e386ee
42 QQmlComponent::completeCreate qqmlcomponent.cpp 957 0x7ffff6e386a0
43 QQmlComponent::create qqmlcomponent.cpp 791 0x7ffff6e37edd
44 QQuickView::continueExecute qquickview.cpp 476 0x7ffff7b720d4
45 QQuickViewPrivate::execute qquickview.cpp 124 0x7ffff7b7101f
46 QQuickView::setSource qquickview.cpp 253 0x7ffff7b71426
47 main main.cpp 24 0x4033e4
在回溯中,可以看到在加載文件時計算了子項的anchors.fill
錨點(第 35、36 幀)。 這會導致子項的寬度發生變化(第 31 幀),從而導致對父項上“寬度”屬性(第 17 幀)的綁定進行綁定更新(第 25 幀)。 這反過來又會強制重新計算子錨點(第 14 幀),這會更改子錨點的寬度(第 10 幀),從而更新綁定(第 4 幀)。 這與已在第 25 幀中更新的綁定相同,因此存在綁定循環。 可以看到第25幀和第4幀的this
指針是一樣的,即遞歸更新同一個綁定。
非常感謝您的收據,但它對我沒有幫助。 如果有人需要它,請添加另一個可能的解決方案。 我在ListView
得到綁定循環,試圖將所有項目寬度和列表寬度設置為項目最大值:
ListView {
implicitWidth: contentItem.childrenRect.width
delegate: listItem
}
Item {
id: listItem
width: Math.max(internalWidth, listView.implicitWidth)
}
綁定循環錯誤出現在項目計數更新上,但不是每次都出現 - 僅在某些批量綁定更新上出現,而沒有實際的綁定循環。 能夠通過將綁定表達式移動到綁定 QML 類型並向其添加delayed
屬性來解決該問題:
Item { // Item causing binding loop
Binding on item_property_causing_loop {
value: <binding_expression>
when: <when_expression> // Optional however could also help
delayed: true // Prevent intermediary values from being assigned
}
}
所以在我的情況下是:
Item { // Item causing binding loop
id: listItem
Binding on width {
value: Math.max(internalWidth, listView.implicitWidth)
when: index >= 0 // Optional however could also help
delayed: true // Prevent intermediary values from being assigned
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.