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

我们应用程序的下一步是在拖动时移动列表中的项目,以便重新排序列表。为此,我们在应用程序中引入了三种新类型:DelegateModelDragDropArea

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.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 的模型项目。DelegateModelitems 属性提供了对视图项目的访问,允许我们在不修改源模型的情况下更改可见顺序。要确定项的当前可见索引,我们可以使用itemsIndex {itemsIndex} 属性,该属性位于委托项的DelegateModel 附件属性中。

要将DelegateModelListView 结合使用,我们将其绑定到视图的model 属性,并将modeldelegate 绑定到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

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