首页 > 解决方案 > 在 GridView 中交换元素

问题描述

我正在编写一个 QML 程序,它本质上是一个 4x4 GridView,里面填充了编号的矩形。我希望能够:

  1. 从网格中交换两个元素,拖放

  2. 仅允许直接相邻元素的交换

我目前的问题是,一旦我将一个元素拖到另一个元素之上,整个网格就会调整位置,填充元素最初所在的位置。有什么方法可以避免该类型网格的自动调整行为?

我知道下面的一段代码可能是造成这种行为的原因,我只是不知道如何以适当的方式改变它。

DropArea {
            anchors { fill: parent; margins: 15 }
            onEntered: {visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)}
        }

完整代码:

import QtQuick 2.0
import QtQml.Models 2.1

GridView {
    id: root
    width: 320; height: 480
    cellWidth: 80; cellHeight: 80

    displaced: Transition {
        NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }//Animação anima a transicao dos tiles
    }

    model: DelegateModel {
        id: visualModel
        model: ListModel {
            id: colorModel
            ListElement { color: "lightsteelblue" ; text: "1" }
            ListElement { color: "lightsteelblue" ; text: "2" }
            ListElement { color: "lightsteelblue" ; text: "3" }
            ListElement { color: "lightsteelblue" ; text: "4" }
            ListElement { color: "lightsteelblue" ; text: "5" }
            ListElement { color: "lightsteelblue" ; text: "6" }
            ListElement { color: "lightsteelblue" ; text: "7" }
            ListElement { color: "lightsteelblue" ; text: "8" }
            ListElement { color: "lightsteelblue" ; text: "9" }
            ListElement { color: "lightsteelblue" ; text: "10" }
            ListElement { color: "lightsteelblue" ; text: "11" }
            ListElement { color: "lightsteelblue" ; text: "12" }
            ListElement { color: "lightsteelblue" ; text: "13" }
            ListElement { color: "lightsteelblue" ; text: "14" }
            ListElement { color: "lightsteelblue" ; text: "15" }
            ListElement { color: "transparent"  }
        }

        delegate: MouseArea {
            id: delegateRoot

            property int visualIndex: DelegateModel.itemsIndex

            width: 80; height: 80
            drag.target: icon

            Rectangle {
                id: icon
                Text {
                   text: model.text
                   font.pointSize: 30
                   anchors.centerIn: parent
                }
                width: 72; height: 72
                anchors {
                    horizontalCenter: parent.horizontalCenter;
                    verticalCenter: parent.verticalCenter
                }
                color: model.color
                radius: 3

                Drag.active: delegateRoot.drag.active
                Drag.source: delegateRoot
                Drag.hotSpot.x: 36
                Drag.hotSpot.y: 36

                states: [
                    State {
                        when: icon.Drag.active
                        ParentChange {
                            target: icon
                            parent: root
                        }

                        AnchorChanges {
                            target: icon;
                            anchors.horizontalCenter: undefined;
                            anchors.verticalCenter: undefined
                        }
                    }
                ]
            }

            DropArea {
                anchors { fill: parent; margins: 15 }
                onEntered: {visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)}
            }
        }
    }
}

标签: androidqtgridviewdrag-and-dropqml

解决方案


我尝试了一些东西,但这里和那里仍然很少有错误。希望能帮助到你。

import QtQuick 2.0
import QtQml.Models 2.1

GridView {
id: root
width: 320; height: 480
cellWidth: 80; cellHeight: 80

displaced: Transition {
    NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }//Animação anima a transicao dos tiles
}

model: DelegateModel {
    id: visualModel
    model: ListModel {
        id: colorModel
        ListElement { color: "lightsteelblue" ; text: "1" }
        ListElement { color: "lightsteelblue" ; text: "2" }
        ListElement { color: "lightsteelblue" ; text: "3" }
        ListElement { color: "lightsteelblue" ; text: "4" }
        ListElement { color: "lightsteelblue" ; text: "5" }
        ListElement { color: "lightsteelblue" ; text: "6" }
        ListElement { color: "lightsteelblue" ; text: "7" }
        ListElement { color: "lightsteelblue" ; text: "8" }
        ListElement { color: "lightsteelblue" ; text: "9" }
        ListElement { color: "lightsteelblue" ; text: "10" }
        ListElement { color: "lightsteelblue" ; text: "11" }
        ListElement { color: "lightsteelblue" ; text: "12" }
        ListElement { color: "lightsteelblue" ; text: "13" }
        ListElement { color: "lightsteelblue" ; text: "14" }
        ListElement { color: "lightsteelblue" ; text: "15" }
        ListElement { color: "transparent" ; text:"" }
    }

    delegate: MouseArea {
        id: delegateRoot
        property bool held: false
        property int visualIndex: DelegateModel.itemsIndex

        width: 80; height: 80
        drag.target: held ? icon : undefined
        drag.axis: Drag.XAndYAxis
        drag.minimumX: delegateRoot.x-75
        drag.minimumY: delegateRoot.y-75
        drag.maximumX: delegateRoot.x + 85
        drag.maximumY: delegateRoot.y + 85

        onPressed: {
                            held = true
                            icon.opacity = 0.5
                        }
                        onReleased: {
                            if (held === true) {
                                held = false
                                icon.opacity = 1
                                icon.Drag.drop()
                            } else {
                                //action on release
                            }
                        }

        Rectangle {
            id: icon
            Text {
               text: model.text
               font.pointSize: 30
               anchors.centerIn: parent
            }
            width: 72; height: 72
            anchors {
                horizontalCenter: parent.horizontalCenter;
                verticalCenter: parent.verticalCenter
            }
            color: model.color
            radius: 3

            Drag.active: delegateRoot.drag.active
            Drag.source: delegateRoot
            Drag.hotSpot.x: 36
            Drag.hotSpot.y: 36
            states: [
                State {
                    when: icon.Drag.active
                    ParentChange {
                        target: icon
                        parent: root
                    }

                    AnchorChanges {
                        target: icon;
                        anchors.horizontalCenter: undefined;
                        anchors.verticalCenter: undefined
                    }
                }
            ]
        }

        DropArea {
            anchors {
                                   fill: parent
                                   margins: 15
                    }
            onDropped: {
                var sourceNumber = colorModel.get(drag.source.visualIndex).text;
                var targetNumber = colorModel.get(delegateRoot.visualIndex).text;
                var sourceColor = colorModel.get(drag.source.visualIndex).color;
                var targetColor = colorModel.get(delegateRoot.visualIndex).color;
                colorModel.setProperty(drag.source.visualIndex, "text", targetNumber);
                colorModel.setProperty(delegateRoot.visualIndex, "text", sourceNumber);
                colorModel.setProperty(drag.source.visualIndex, "color", targetColor);
                colorModel.setProperty(delegateRoot.visualIndex, "color", sourceColor);
            }
        }
    }
}
}

推荐阅读