如何分析"绑定循环"

Mar*_*ele 5 qt qml

我有一个带有C++模型和QML可视化的Qt/QML应用程序.

在运行时(启动),我收到警告

QML项:检测属性"xyz"的绑定循环

我在QML中看不到明显的循环.我可以启用更多调试来了解此循环的来源吗?其他建议?

Tho*_*ire 8

我通常通过在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
    }
}
Run Code Online (Sandbox Code Playgroud)

回溯:

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    
Run Code Online (Sandbox Code Playgroud)

在回溯中,可以看到anchors.fill在加载文件时计算子项的锚(框架35,36).这会导致子项的宽度发生变化(第31帧),这会导致对父项的"width"属性(第17帧)上的绑定进行绑定更新(第25帧).这又强制重新计算子锚(框架14),这改变了儿童的宽度(框架10),这更新了绑定(框架4).这是在第25帧中已经更新的相同绑定,因此存在绑定循环.可以看出this帧25和帧4中的指针是相同的,即递归地更新相同的绑定.

  • https://bugreports.qt.io 上是否有功能请求以默认启用有用的调试打印输出?我很想能够投票支持它,但我的 google-foo 无法胜任这项任务。 (2认同)