使用ListView拖放创建库存UI

时间:2014-09-25 18:29:05

标签: qt listview drag-and-drop qml

我想使用ListView为我的游戏创建一个库存用户界面,通过在级别中拖放项目,可以从库存中删除这些项目。如果物品未正确掉落(仍在库存内),则应将其放回拖拽前的位置。

我已经获得了以下代码,但即使在查看Drag and Drop example之后,我也不知道如何实现我的目标。

import QtQuick 2.3

Rectangle {
    id: root
    width: 400
    height: 400

    ListView {
        id: listView
        width: parent.width / 2
        height: parent.height

        model: ListModel {
            Component.onCompleted: {
                for (var i = 0; i < 10; ++i) {
                    append({value: i});
                }
            }
        }

        delegate: Item {
            id: delegateItem
            width: listView.width
            height: 50

            Rectangle {
                id: dragRect
                width: listView.width
                height: 50
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
                color: "salmon"
                border.color: Qt.darker(color)

                Text {
                    anchors.centerIn: parent
                    text: modelData
                }

                MouseArea {
                    id: mouseArea
                    anchors.fill: parent
                    drag.target: dragRect
                }

                Drag.hotSpot.x: dragRect.width / 2
                Drag.hotSpot.y: dragRect.height / 2
            }
        }
    }

    Rectangle {
        width: parent.width / 2
        height: parent.height
        anchors.right: parent.right
        color: "#aaff0011"

        DropArea {
            id: dropArea
            anchors.fill: parent
        }
    }
}

1 个答案:

答案 0 :(得分:6)

您可以使用以下代码实现此目的:

import QtQuick 2.3

Rectangle {
    id: root
    width: 400
    height: 400

    ListView {
        id: listView
        width: parent.width / 2
        height: parent.height

        property int dragItemIndex: -1

        model: ListModel {
            Component.onCompleted: {
                for (var i = 0; i < 10; ++i) {
                    append({value: i});
                }
            }
        }

        delegate: Item {
            id: delegateItem
            width: listView.width
            height: 50

            Rectangle {
                id: dragRect
                width: listView.width
                height: 50
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
                color: "salmon"
                border.color: Qt.darker(color)

                Text {
                    anchors.centerIn: parent
                    text: modelData
                }

                MouseArea {
                    id: mouseArea
                    anchors.fill: parent
                    drag.target: dragRect

                    drag.onActiveChanged: {
                        if (mouseArea.drag.active) {
                            listView.dragItemIndex = index;
                        }
                        dragRect.Drag.drop();
                    }
                }

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

                        AnchorChanges {
                            target: dragRect
                            anchors.horizontalCenter: undefined
                            anchors.verticalCenter: undefined
                        }
                    }
                ]

                Drag.active: mouseArea.drag.active
                Drag.hotSpot.x: dragRect.width / 2
                Drag.hotSpot.y: dragRect.height / 2
            }
        }
    }

    Rectangle {
        width: parent.width / 2
        height: parent.height
        anchors.right: parent.right
        color: "#aaff0011"

        DropArea {
            id: dropArea
            anchors.fill: parent
            onDropped: {
                listView.model.remove(listView.dragItemIndex);
                listView.dragItemIndex = -1;
            }
        }
    }
}

此示例中需要注意的一些事项:

  1. 我们存储dragItemIndex,以便我们知道正在拖动哪个项目。我们可以通过查看DropArea的drag.source属性来实现相同的功能,但是我们必须在委托中公开索引属性,并documentation discourages storing state in delegates

  2. 为了实现“将项目放回到不成功拖动的位置”功能,我们使dragRect成为实际委托项的子项,以便它有一个父项可以坚持。如果我们不这样做,那么项目的父项将是ListView,并且当未成功删除时,它将只是放在最后拖动的位置。

  3. 我们使用与Drag and Drop example相同的状态更改行为;在拖动时,我们想要从项目中移除锚点并让它自由拖动。如果拖动失败,则状态when条件(dragRect.Drag.active)将变为false,并且该项目将作为父级的父级,并且不会从列表视图中的原始位置移动。锚也恢复了。这是各州的有用特征;能够隐含地恢复以前的状态。

  4. MouseArea的{​​{1}}信号处理程序中,我们致电drag.onActiveChanged,以便我们可以在dragRect.Drag.drop()的{​​{1}}中回复该事件信号处理程序,并删除该项目。删除该项后,我们会将DropArea重置为无效索引。