Sur cette page

Tutoriel 3 sur le tri dynamique des éléments dans une vue QML – Déplacement des éléments glissés

La prochaine étape de notre application consiste à déplacer les éléments au sein de la liste lorsqu'ils sont glissés, afin de pouvoir réorganiser la liste. Pour ce faire, nous introduisons trois nouveaux types dans notre application : DelegateModel, Drag et 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)
                }
            }
        }
    }
}
Procédure pas à pas

Afin de réorganiser la vue, nous devons déterminer quand un élément a été glissé par-dessus un autre. Grâce à la propriété attachée Drag, nous pouvons générer des événements qui sont envoyés au graphe de scène chaque fois que l'élément auquel elle est attachée se déplace.

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

Les événements « Drag » ne sont envoyés que lorsque la propriété « active » est à « true » ; ainsi, dans cet exemple, le premier événement serait envoyé lorsque le délégué est maintenu enfoncé, puis d’autres événements seraient envoyés pendant le glissement. La propriété « hotSpot » spécifie la position relative des événements « Drag » au sein de l’élément glissé, c’est-à-dire le centre de l’élément dans ce cas précis.

Nous utilisons ensuite un ` DropArea ` dans chaque élément de la vue pour déterminer quand la zone sensible de l’élément déplacé entre en intersection avec un autre élément ; lorsqu’un déplacement pénètre dans l’une de ces zones de dépôt (`DropAreas`), nous pouvons déplacer l’élément vers l’index de l’élément sur lequel il a été déplacé.

            DropArea {
                anchors {
                    fill: parent
                    margins: 10
                }

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

Pour déplacer les éléments au sein de la vue, nous utilisons un ` DelegateModel`. Le type ` DelegateModel ` est utilisé par les types de vue pour instancier des éléments délégués à partir des données du modèle et, lorsqu’il est construit explicitement, peut servir à filtrer et réorganiser les éléments du modèle fournis à ` ListView`. La propriété ` items ` de ` DelegateModel ` donne accès aux éléments de la vue et nous permet de modifier l’ordre d’affichage sans modifier le modèle source. Pour déterminer l’index actuel des éléments visibles, nous utilisons la propriété ` itemsIndex {itemsIndex}` de la propriété attachée ` DelegateModel ` de l’élément délégué.

Pour utiliser un DelegateModel avec un ListView, nous le lions à la propriété model de la vue et lions les propriétés model et delegate à la propriété DelegateModel.

    DelegateModel {
        id: visualModel

        model: PetsModel {}
        delegate: dragDelegate
    }

    ListView {
        id: view

        anchors {
            fill: parent
            margins: 2
        }

        model: visualModel

        spacing: 4
        cacheBuffer: 50
    }

Exemple de projet sur 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.