QML Dynamic View Ordering Tutorial 3 - Verschieben gezogener Elemente

Der nächste Schritt in unserer Anwendung besteht darin, Elemente innerhalb der Liste zu verschieben, wenn sie gezogen werden, so dass wir die Liste neu anordnen können. Um dies zu erreichen, führen wir drei neue Typen in unsere Anwendung ein: DelegateModel, Drag und 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)
                }
            }
        }
    }
}
Exkursion

Um die Ansicht neu anordnen zu können, müssen wir feststellen, wann ein Element über ein anderes gezogen wurde. Mit der Eigenschaft Drag attached können wir Ereignisse erzeugen, die an den Szenegraphen gesendet werden, sobald sich das Element, an das es angehängt ist, bewegt.

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

Ziehereignisse werden nur gesendet, wenn die aktive Eigenschaft wahr ist. In diesem Beispiel würde das erste Ereignis gesendet werden, wenn das Delegat gehalten wird, und weitere Ereignisse werden beim Ziehen gesendet. Die Eigenschaft hotSpot gibt die relative Position der Ziehereignisse innerhalb des gezogenen Elements an, in diesem Fall die Mitte des Elements.

Dann verwenden wir DropArea in jedem Ansichtselement, um zu bestimmen, wann der Hotspot des gezogenen Elements ein anderes Element schneidet. Wenn ein Ziehen in einen dieser DropAreas eintritt, können wir das gezogene Element zum Index des Elements verschieben, über das es gezogen wurde.

            DropArea {
                anchors {
                    fill: parent
                    margins: 10
                }

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

Um die Elemente innerhalb der Ansicht zu verschieben, verwenden wir DelegateModel. Der Typ DelegateModel wird von den Ansichtstypen verwendet, um Elemente aus Modelldaten zu instanziieren, und wenn er explizit konstruiert wird, kann er verwendet werden, um die Modellelemente, die ListView zur Verfügung gestellt werden, zu filtern und neu zu ordnen. Die Eigenschaft items von DelegateModel bietet Zugriff auf die Elemente der Ansicht und ermöglicht es uns, die sichtbare Reihenfolge zu ändern, ohne das Quellmodell zu verändern. Um den aktuellen sichtbaren Index der Elemente zu bestimmen, verwenden wir die itemsIndex {itemsIndex} Eigenschaft der DelegateModel angehängten Eigenschaft des Delegatenelements.

Um eine DelegateModel mit einer ListView zu verwenden, binden wir sie an die model Eigenschaft der Ansicht und binden die model und delegate an die DelegateModel.

    DelegateModel {
        id: visualModel

        model: PetsModel {}
        delegate: dragDelegate
    }

    ListView {
        id: view

        anchors {
            fill: parent
            margins: 2
        }

        model: visualModel

        spacing: 4
        cacheBuffer: 50
    }

Beispielprojekt @ code.qt.io

© 2025 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.