Drag-and-drop functionality is a common requirement in client applications. For QWidget-based programs, overriding specific methods (as shown in Figure 1) allows control over drag logic. However, QDrag's exec operation blocks the main event loop, preventing other interfaces from responding to mouse eveents. To address a scenario where the main interface needed to remain rseponsive, the author previously simulated program dragging by overriding interfaces like those in Figure 2.
Figure 1: QWidget Drag Interfaces
Figure 2: QWidget Mouse Event Interfaces
The example demonstrates drag-and-drop between three large text input fields, allowing text to be moved between them (Figure 3).
Figure 3: Example Drag-and-Drop
Source Code Analysis
The example consists of two QML files: a custom component DragAndDropTextItem and the main layout.
1. Custom Component: DragAndDropTextItem
The root node of DragAndDropTextItem is a Rectangle that supports mouse events. A MouseArea captures all mouse events on the root node and sets the drag target to the draggable component. The DropArea contains several slot functions automatically called during drag operations, such as onEntered (when the mouse enters) and onExited (when the mouse leaves). The code is as follows:
import QtQuick 2.2
Rectangle {
id: container
property string textContent
color: "#EEE"
Text {
anchors.fill: parent
text: container.textContent
wrapMode: Text.WordWrap
}
DropArea {
anchors.fill: parent
keys: ["text/plain"]
onEntered: {
container.color = "#FCC"
}
onExited: {
container.color = "#EEE"
}
onDropped: {
container.color = "#EEE"
if (drop.hasText) {
if (drop.proposedAction === Qt.MoveAction || drop.proposedAction === Qt.CopyAction) {
container.textContent = drop.text
drop.acceptProposedAction()
}
}
}
}
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: dragSource
}
Item {
id: dragSource
anchors.fill: parent
Drag.active: dragArea.drag.active
Drag.hotSpot.x: 10
Drag.hotSpot.y: 10
Drag.mimeData: { "text/plain": container.textContent }
Drag.dragType: Drag.Automatic
Drag.onDragStarted: {
}
Drag.onDragFinished: {
if (dropAction === Qt.MoveAction) {
container.textContent = ""
}
}
}
}
2. Main Layout
The main interface uses a ColumnLayout. The first row displays a description text, followed by three DragAndDropTextItem components. The code is as follows:
import QtQuick 2.2
import QtQuick.Layouts 1.0
Item {
id: root
width: 320
height: 480
ColumnLayout {
anchors.fill: parent
anchors.margins: 8
Text {
Layout.fillWidth: true
text: "Drag text into, out of, and between the boxes below."
wrapMode: Text.WordWrap
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
textContent: "Sample Text"
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
textContent: "Option/ctrl drag to copy instead of move text."
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
textContent: "Drag out into other applications."
}
}
}