En esta página

QML Dynamic View Ordering Tutorial 3 - Mover elementos arrastrados

El siguiente paso en nuestra aplicación consiste en mover elementos dentro de la lista a medida que son arrastrados, de forma que podamos reordenar la lista. Para ello introducimos tres nuevos tipos en nuestra aplicación; DelegateModel, Drag y DropArea.

Rectangle {
    id: root

    width: 300
    height: 400

    Component {
        id: dragDelegate

        MouseArea {
            id: dragArea

            property bool held: false
            required property string name
            required property string type
            required property string size
            required property int age

            anchors {
                left: parent?.left
                right: parent?.right
            }
            height: content.height

            drag.target: held ? content : undefined
            drag.axis: Drag.YAxis

            onPressAndHold: held = true
            onReleased: held = false

            Rectangle {
                id: content
                Drag.active: dragArea.held
                Drag.source: dragArea
                Drag.hotSpot.x: width / 2
                Drag.hotSpot.y: height / 2
            }
            DropArea {
                anchors {
                    fill: parent
                    margins: 10
                }

                onEntered: (drag) => {
                    visualModel.items.move(
                            drag.source.DelegateModel.itemsIndex,
                            dragArea.DelegateModel.itemsIndex)
                }
            }
        }
    }
}
Recorrido

Para poder reordenar la vista necesitamos determinar cuando un elemento ha sido arrastrado sobre otro. Con la propiedad Drag attached podemos generar eventos que se envían al gráfico de la escena cada vez que el elemento al que está unido se mueve.

                Drag.active: dragArea.held
                Drag.source: dragArea
                Drag.hotSpot.x: width / 2
                Drag.hotSpot.y: height / 2

Los eventos de arrastre sólo se envían mientras la propiedad active es true, por lo que en este ejemplo el primer evento se enviaría cuando se mantuviera el delegado con envíos de eventos adicionales al arrastrar. La propiedad hotSpot especifica la posición relativa de los eventos de arrastre dentro del elemento arrastrado, el centro del elemento en este caso.

Luego usamos un DropArea en cada ítem de la vista para determinar cuando el punto caliente del ítem arrastrado intersecta otro ítem, cuando un arrastre entra en una de estas DropAreas podemos mover el ítem arrastrado al índice del ítem sobre el que fue arrastrado.

            DropArea {
                anchors {
                    fill: parent
                    margins: 10
                }

                onEntered: (drag) => {
                    visualModel.items.move(
                            drag.source.DelegateModel.itemsIndex,
                            dragArea.DelegateModel.itemsIndex)
                }
            }

Para mover los elementos dentro de la vista utilizamos un DelegateModel. El tipo DelegateModel es utilizado por los tipos de vista para instanciar elementos delegados a partir de datos del modelo y cuando se construye explícitamente puede utilizarse para filtrar y reordenar los elementos del modelo proporcionados a ListView. La propiedad items de DelegateModel proporciona acceso a los elementos de la vista y nos permite cambiar el orden visible sin modificar el modelo fuente. Para determinar el índice visible actual de los elementos utilizamos la propiedad itemsIndex {itemsIndex} de la propiedad adjunta DelegateModel del elemento delegado.

Para utilizar un DelegateModel con un ListView lo vinculamos a la propiedad model de la vista y vinculamos los model y delegate a la DelegateModel.

    DelegateModel {
        id: visualModel

        model: PetsModel {}
        delegate: dragDelegate
    }

    ListView {
        id: view

        anchors {
            fill: parent
            margins: 2
        }

        model: visualModel

        spacing: 4
        cacheBuffer: 50
    }

Proyecto de ejemplo @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.