Getting binding loop when checking mousearea.containsMouse on a drag operation
-
I cannot tell why I am getting a binding loop here.
main.qml:
import QtQuick 2.12 import QtQuick.Window 2.12 Window { visible: true width: 640 height: 480 title: qsTr("Dragon Drop: drag to window") ColorAnimation on color { id: rejectAnimation running: false from: "#FCC" to: "#EEE" duration: 1000 } DropArea { id: dropArea anchors.fill: parent keys: ["amet/displaykey"] onEntered: (drag) => { if(drag.proposedAction != Qt.CopyAction){ drag.accepted = false rejectAnimation.start() } } onDropped: (drop) => { var textdata = drop.getDataAsString(keys[0]) if (textdata.length) { if (drop.proposedAction == Qt.CopyAction) { console.log(textdata) drop.acceptProposedAction() } } } } Window { id: side_window title: "drag from window" visible: true width: 400 height: 400 MouseArea { id: mousearea hoverEnabled: true width: parent.width height: parent.height } DragIcon { visible: mousearea.containsMouse dropdata: ({ "display": "some data" }) dragtext: "✋" dragkeys: ["displaykey"] dragmime: {"amet/displaykey":dropdata} } } }
DragIcon.qml:
import QtQuick 2.15 import QtQuick.Controls 2.15 Rectangle { id: grab_handle width: 20 height: 20 property int dragwidth: 20 property int dragheight: 20 property string dragtext property string draggedtext: dragtext property var dragkeys: [] property var dragmime: ({}) property var dropdata: ({}) property var dragparent color: "transparent" border.color: "steelblue" border.width: 1 Text { id: drag_text anchors.centerIn: parent text: grab_handle.dragtext } MouseArea { id: drag_mousearea anchors.fill: parent drag.target: draggable onReleased: { draggable.Drag.drop() } onPressed: draggable.grabToImage(function(result) { draggable.Drag.imageSource = result.url }) Rectangle { id: draggable objectName: "draggable" visible: drag_mousearea.drag.active width: grab_handle.dragwidth height: grab_handle.dragheight color: "transparent" border.color: grab_handle.border.color border.width: 1 property var dropdata: grab_handle.dropdata Drag.active: drag_mousearea.drag.active Drag.hotSpot.x: 0 Drag.hotSpot.y: 0 Drag.keys: grab_handle.dragkeys Drag.dragType: Drag.Automatic Drag.supportedActions: Qt.CopyAction Drag.mimeData: dragmime Drag.onDragFinished: { Qt.callLater(fixpos, x,y) // fixes drag glitches } function fixpos(x, y){ draggable.x = x draggable.y =y } //states: State { //when: drag_mousearea.drag.active //ParentChange { target: draggable; parent: grab_handle.dragparent } //AnchorChanges { target: draggable; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined } //} Text { id: dragged_text anchors.centerIn: parent text: grab_handle.draggedtext } } } }
I think it has something to do with the mousearea active, but I just don't see why there is a loop.
The error occurs once when starting the drag:
qrc:/DragIcon.qml:47:9: QML Rectangle (parent or ancestor of QQuickDragAttached): Binding loop detected for property "active"
If I don't use mousearea.containsMouse in main.qml to determine visibility it doesn't show this binding loop. Which makes no sense to me.
Everything works as expected so I have been ignoring this. I don't want this to bite me later.Qt 5.15.2 64 bit
Linux -
I found where I learned how to bind mousearea.drag.active to Drag.active. So that part "should" be good. I upgraded from 5.15.1. to 5.15.2 to see if this is a library issue. Not that I can tell.
I just checked and I get the binding loop detection in 5.12.10. So it was not introduced with 5.15.
Are binding loop detections really sensitive? I put an on changed routine on the Drag.active and it only changes once:
Drag.onActiveChanged: console.log("Drag.active:", Drag.active)
-
Okay, I found how to make it go away. I am not sure if this is a good solution, but it seems to get rid of the binding loop message and does not seem to affect functionality.
Change this:
Drag.active: drag_mousearea.drag.active
To this:
// prevents binding loop with unknown cause Binding on Drag.active { value: drag_mousearea.drag.active delayed: true }
-
This is still a known bug, even all the way in 6.6. The problem is with using
Drag.Automatic
fordragType
.
https://bugreports.qt.io/browse/QTBUG-111789
This stackoverlow answer offers an alternative way of skipping bindingmousearea.drag.active
by implementing the signals directly.
https://stackoverflow.com/questions/24532317/new-drag-and-drop-mechanism-does-not-work-as-expected-in-qt-quick-qt-5-3There is a fairly simple workaround: take the best from both worlds. Use Drag.Automatic, but instead of setting Drag.active, call start() and drop() manually. It won't invoke Drag.onDragStarted() and Drag.onDragFinished() but you essentially get those for free anyway by listening for a change in the MouseArea's drag.active.