本页内容

QML 动态视图排序教程 3 - 移动被拖动的项目

我们应用程序的下一步是,在拖动项目时将其在列表中移动,从而重新排序列表。为实现这一功能,我们将向应用程序引入三种新类型:DelegateModel 、Drag 和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)
                }
            }
        }
    }
}
操作指南

为了重新排序视图,我们需要确定一个项目何时被拖拽到另一个项目之上。借助 Drag 附加属性,每当与其关联的项目移动时,我们就能生成并发送事件至场景图。

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

拖动事件仅在 active 属性为 true 时发送,因此在此示例中,当长按委托时会发送第一个事件,并在拖动过程中发送后续事件。hotSpot 属性指定了拖动事件在被拖动物项内的相对位置,在本例中即为该物项的中心。

然后,我们在每个视图项目中使用DropArea 来确定被拖动项目的热区何时与另一个项目相交;当拖动进入这些DropAreas之一时,我们可以将被拖动项目移动到其被拖过的那项的索引位置。

            DropArea {
                anchors {
                    fill: parent
                    margins: 10
                }

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

要在视图内移动项目,我们使用DelegateModel 。DelegateModel 类型由视图类型用于从模型数据实例化委托项目,当显式构造时,可用于过滤和重新排序提供给ListView 的模型项目。DelegateModel 的items 属性可访问视图中的项目,并允许我们在不修改源模型的情况下更改可见顺序。 要确定项目当前的可见索引,我们使用委托项目上DelegateModel 附加属性中的itemsIndex {itemsIndex}属性。

要使用带有 `ListView ` 的 `DelegateModel `,需将其绑定到视图的 `model ` 属性上,并将 `model ` 和 `delegate ` 绑定到 `DelegateModel`。

    DelegateModel {
        id: visualModel

        model: PetsModel {}
        delegate: dragDelegate
    }

    ListView {
        id: view

        anchors {
            fill: parent
            margins: 2
        }

        model: visualModel

        spacing: 4
        cacheBuffer: 50
    }

示例项目 @ 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.