QML Drag and Drop Implementation Analysis

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."
        }
    }
}

Tags: QML qtquick Drag and Drop Qt QtQuick.Layouts

Posted on Sat, 19 Sep 2026 16:37:38 +0000 by goatboy