Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Getting binding loop when checking mousearea.containsMouse on a drag operation
Forum Updated to NodeBB v4.3 + New Features

Getting binding loop when checking mousearea.containsMouse on a drag operation

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 3 Posters 989 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by fcarney
    #1

    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

    C++ is a perfectly valid school of magic.

    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      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)
      

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by
        #3

        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
        }
        

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        1
        • YunusY Offline
          YunusY Offline
          Yunus
          wrote on last edited by
          #4

          I have met the same issue and used the same method. Did you get a problem till now caused by using this ?

          1 Reply Last reply
          0
          • E Offline
            E Offline
            Ed K
            wrote last edited by
            #5

            This is still a known bug, even all the way in 6.6. The problem is with using Drag.Automatic for dragType.
            https://bugreports.qt.io/browse/QTBUG-111789
            This stackoverlow answer offers an alternative way of skipping binding mousearea.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-3

            There 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.
            
            1 Reply Last reply
            0
            • E Offline
              E Offline
              Ed K
              wrote last edited by
              #6

              Unfortunately, the stackoverflow solution doesn't work if you're depending on mime settings or imageSource (or requires some more effort to make it work), but the delayed binding solution did work.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved