Reputation: 341
I have a repeater that generates a bunch of rectangles. I want to be able to drag these rectangles around and generate an event when I drop one rectangle on another (think files and folders on an OS. I can drag folders & files, but I can drop a file on a folder and it stores it inside). I've tried the following but the dropArea gets confused because the object itself is draggable. OnDropped just never triggers. Is this possible?
Repeater {
model: 5
Item {
id: element
Item {
id: surfaceContainer
width: 150
height: 150
x: index * width
DropArea {
id: dropArea
anchors.fill: surfaceContainer
onContainsDragChanged: {
if (containsDrag && drag.source != draggableRectangle)
console.log("CHANGED")
}
onEntered: {
if (drag.source != draggableRectangle)
console.log("ENTERED")
}
onDropped: {
console.log("DROPPED")
}
onExited: {
if (drag.source != draggableRectangle && containsDrag)
drag.source.color = "yellow"
}
}
Rectangle {
id: draggableRectangle
x: width / 2
color: "blue"
height: 100
width: 100
Drag.active: dragArea.drag.active
MouseArea {
id: dragArea
anchors.fill: draggableRectangle
drag.target: draggableRectangle
onDoubleClicked: {
connectionId.visible = !connectionId.visible
}
}
}
}
}
}
Upvotes: 0
Views: 352
Reputation: 25871
[EDIT]
I made the following changes to your application:
DropArea
to match the Rectangle
geometryRectangle
has completed dragging, to re-update the DropArea
to match the Rectangle
geometryRectangle
is being dragged, only enable the DropArea
that are valid destinations, i.e. it can only be dragged to a DropArea
of a different delegateimport QtQuick
import QtQuick.Controls
Page {
property var sourceItem: null
property var destItem: null
property string statusText: ""
Repeater {
model: [ "A", "B", "C", "D", "E" ]
Item {
z: dragArea.drag.active ? 2 : 0
DropArea {
id: dropArea
x: index * 150 + 100
y: 100
width: 100
height: 100
enabled: sourceItem && sourceItem !== modelData
onContainsDragChanged: {
if (containsDrag) {
destItem = modelData;
} else {
destItem = null;
}
}
}
Rectangle {
id: dragRect
x: index * 150 + 100
y: 100
width: 100
height: 100
color: dropArea.containsDrag ? "green" : dragArea.drag.active ? "#c00" : "#f88"
Drag.active: dragArea.drag.active
Drag.hotSpot.x: 10
Drag.hotSpot.y: 10
Label {
anchors.centerIn: parent
text: modelData
}
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
drag.onActiveChanged: {
if (drag.active) {
sourceItem = modelData;
} else {
if (sourceItem && destItem) {
statusText = "Dragged " + JSON.stringify(sourceItem) + " to " + JSON.stringify(destItem);
} else {
statusText = "";
}
sourceItem = null;
dropArea.x = dragRect.x;
dropArea.y = dragRect.y;
}
}
}
}
}
}
Frame {
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height * 3 / 4
visible: statusText
Text {
text: statusText
}
}
}
You can Try it Online!
Upvotes: 1