Solution: Rearranging QAbstractListModel by dragging and dropping in ListView
QML and Qt Quick
1
Posts
1
Posters
63
Views
1
Watching
-
wrote 28 days ago last edited by nova_xo 5 Nov 2025, 11:08
Following is a code snippet that allows for Rearranging QAbstractListModel by dragging and dropping it's ListView delegates. It is fully dynamic.
I couldn't find any official documentation for this and what I did find was very obscure. I've been trying to get this in a project of mine for a week now and finally found a solution. All of the following code has been tested in Qt 6.9
ListView { id: listview width: parent.width height: parent.height z: 5 spacing: 10 anchors { top: label_br.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } displaced: Transition { NumberAnimation { properties: "x,y" easing.type: Easing.OutQuad } } model: DelegateModel { id: visualModel model: Model delegate: DropArea { id: delegateRoot required property var modelData property int visualIndex: DelegateModel.itemsIndex property int modelIndex height: queue_item.fontsize * 2 width: listview.width * 0.95 anchors.horizontalCenter: parent?.horizontalCenter onEntered: function (drag) { var from = (drag.source as Queue_tile).visualIndex var to = tile.visualIndex visualModel.items.move(from, to) } onDropped: function (drag) { var from = modelIndex var to = (drag.source as Queue_tile).visualIndex Model.move(from, to) } Queue_tile { id: tile height: queue_item.fontsize * 2 width: listview.width * 0.95 dragParent: listview visualIndex: delegateRoot.visualIndex onPressed: delegateRoot.modelIndex = visualIndex color: "transparent" //Your content. make sure it doesnt already contain a mousearea as that will interfere with the tile wrapper Queue_item { id: queue_item title: delegateRoot.modelData.title anchors.centerIn: parent width: listview.width * 0.95 } } } } }
Queue_tile.qml
import QtQuick Rectangle { id: root required property Item dragParent signal pressed signal released signal clicked property int visualIndex: 0 anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } radius: 3 MouseArea { id: mouseArea anchors.fill: parent drag.target: root onClicked: root.clicked() onPressed: root.pressed() onReleased: { parent.Drag.drop() root.released() } } Drag.active: mouseArea.drag.active Drag.source: root Drag.hotSpot.x: root.width / 2 Drag.hotSpot.y: root.height / 2 states: [ State { when: mouseArea.drag.active ParentChange { target: root parent: root.dragParent } AnchorChanges { target: root anchors.horizontalCenter: undefined anchors.verticalCenter: undefined } } ] }
Credits: It has been adapted from the gridview implementation from https://raymii.org/s/tutorials/Qml_Drag_and_Drop_example_including_reordering_the_Cpp_Model.html . It's an old solution and hadn't been tested in latest versions of Qt.
-
1/1