2016-07-05 14 views
4

Ich habe eine Qt/QML-Anwendung mit einem C++ - Modell und einer QML-Visualisierung.Wie man eine "Binding-Schleife" analysiert

Zur Laufzeit (Start-up), erhalte ich eine Warnung

QML Item: Schleife für Eigenschaft "xyz" erkannt Bindung

ich keine offensichtliche Schleife in meinem QML zu sehen. Kann ich mehr Debugging aktivieren, um zu verstehen, woher diese Schleife kommt? Andere Vorschläge?

+0

Ich bin mir nicht sicher, aber IIRC qml Profiler können Sie verbindliche Anrufe sehen. Sie können auch eine Console Debug-Ausgabe in Eigenschaftenzuweisungen hinzufügen. Und du kannst deinen Code hier posten, damit wir dir helfen können :) –

+0

Danke für deine Eingabe. Der QML-Profiler zeigt tatsächlich QML-Bindungsaufrufe an. Wie auch immer, afaics, zeigt es nicht, welcher zugrundeliegende C++ Code in der Schleife involviert ist. Ich habe (und hoffe immer noch) auf einige Protokolle gehofft, die z. "a bindet an b" "b bindet an c" "c bindet an eine" –

+0

Nun, wenn es eine Option dafür gibt, weiß ich es nicht. Aber das mache ich manchmal, um Loops zu debuggen: 'height: {console.debug (" binding height "); return parent.height; } '. Beachten Sie, dass dies keine Bindung selbst erzeugt, Sie müssen 'Qt.binding ...' verwenden http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html –

Antwort

5

Normalerweise mache ich dies, indem ich einen Haltepunkt im Qt-Code platziere, der die Warnung ausgibt. Dafür benötigen Sie ein Qt mit Debug-Symbolen.

Suche nach "Binding Loop erkannt" in den Qt-Quellen gibt mir QQmlAbstractBinding::printBindingLoopError(). Wenn Sie dort einen Haltepunkt platzieren, führt dies in der Regel zu einem Backtrace, der ein klares Bild der Situation liefert.

Update: David Edmundson hat ein kleines Tool entwickelt, das eine QML-Backtrace auf Bindungsschleifen anzeigt, siehe his blog here. Unter der Haube tut genau das, was hier beschrieben wird, nur dass es schön automatisiert und in ein Python-Skript eingebunden ist.

Beispiel:

Rectangle { 
    id: parent 
    width: child.width + 1 
    height: child.height + 1 
    Rectangle { 
     id: child 
     anchors.fill: parent 
    } 
} 

Backtrace:

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  

In der Backtrace, kann man sehen, dass die anchors.fill Anker für das untergeordnete Element berechnet wird, wenn das Laden der Datei (Rahmen 35, 36). Das bewirkt, dass sich die Breite des untergeordneten Elements ändert (Frame 31), was eine Bindungsaktualisierung (Frame 25) für eine Bindung an die "width" -Eigenschaft (Frame 17) des übergeordneten Elements verursacht. Dies zwingt wiederum eine Neuberechnung der Kindanker (Rahmen 14), was die Breite des Kindes (Rahmen 10) ändert, wodurch eine Bindung aktualisiert wird (Rahmen 4). Das ist die gleiche Bindung, die bereits in Rahmen 25 aktualisiert wurde, daher existiert eine Bindungsschleife. Man kann sehen, dass der Zeiger in Rahmen 25 und Rahmen 4 gleich sind, d. H. Die gleiche Bindung wird rekursiv aktualisiert.

+0

Das sieht vielversprechend aus! Kannst du mir zeigen, wie man ein "Qt mit Debug-Symbolen" bekommt? Sollte ich Qt selbst kompilieren? –

+0

Wenn Sie Linux verwenden, installieren Sie die Pakete '* -dbg'. – Velkan

+0

Ich kompiliere Qt selbst aus der Quelle, also übergebe ich einfach das '' -debug'' Flag an '' configure''. Keine Ahnung von vorgefertigten Paketen. –