QML Drag and Drop (free positioning)

ndothenning picture ndothenning · Jun 22, 2015 · Viewed 9.6k times · Source

There are a lot of QML Drag and Drop Examples out there, but none of them really helps me, because in all the examples you can drag an element into another, where it is centered and all other elements you drag above are laying over it.

Is there a way to have some elements on one side and on the other side a big Rectangle where you can drag them in, drop them anywhere inside of it and they stay on their exact drop position?

For example, if I got a Rectangle with width: 200; height: 200 and I drag an element in, such an element should stay at the position I've dropped it, e.g. x: 25 and y: 65. That should be the position of the element.

Do you have any suggestions?

Answer

folibis picture folibis · Jun 23, 2015

It is very simple just to set drag.target to make an Item draggable, as @qCring already noticed. Dropping the dragged Item doesn't change its position at all. Anyway, maybe this small example can help you:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: win
    width: 800
    height: 600
    title: "Drag & drop example"
    visible: true

    Repeater {
        model: 10
        Rectangle {
            id: rect
            width: 50
            height: 50
            z: mouseArea.drag.active ||  mouseArea.pressed ? 2 : 1
            color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
            x: Math.random() * (win.width / 2 - 100)
            y: Math.random() * (win.height - 100)
            property point beginDrag
            property bool caught: false
            border { width:2; color: "white" }
            radius: 5
            Drag.active: mouseArea.drag.active

            Text {
                anchors.centerIn: parent
                text: index
                color: "white"
            }
            MouseArea {
                id: mouseArea
                anchors.fill: parent
                drag.target: parent
                onPressed: {
                    rect.beginDrag = Qt.point(rect.x, rect.y);
                }
                onReleased: {
                    if(!rect.caught) {
                        backAnimX.from = rect.x;
                        backAnimX.to = beginDrag.x;
                        backAnimY.from = rect.y;
                        backAnimY.to = beginDrag.y;
                        backAnim.start()
                    }
                }

            }
            ParallelAnimation {
                id: backAnim
                SpringAnimation { id: backAnimX; target: rect; property: "x"; duration: 500; spring: 2; damping: 0.2 }
                SpringAnimation { id: backAnimY; target: rect; property: "y"; duration: 500; spring: 2; damping: 0.2 }
            }
        }
    }

    Rectangle {
        anchors {
            top: parent.top
            right:  parent.right
            bottom:  parent.bottom
        }
        width: parent.width / 2
        color: "gold"
        DropArea {
            anchors.fill: parent
            onEntered: drag.source.caught = true;
            onExited: drag.source.caught = false;
        }
    }
}

Item can be dragged into yellow box but not back. Made it just for fun.