使用 ListView 拖放来创建清单 UI [英] Using drag and drop with ListView to create an inventory UI

查看:18
本文介绍了使用 ListView 拖放来创建清单 UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 ListView 为我的游戏创建一个物品栏 UI,可以通过在关卡中拖放物品来从物品栏中移除物品.如果物品没有被正确放下(仍在物品栏中),则应将其放回拖动前的位置.

I'd like to create an inventory UI for my game using ListView, where the items can be removed from the inventory by dragging and dropping them in the level. If an item was not dropped properly (still inside the inventory), it should be placed back where it was before the drag.

我有以下代码,但我不知道如何实现我所追求的,即使查看了 拖放示例.

I've got the following code, but I don't know how to achieve what I'm after, even after looking at the 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
        }
    }
}

推荐答案

您可以使用以下代码实现:

You can achieve this with the following code:

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;
            }
        }
    }
}

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

Some things to notice in this example:

  1. 我们存储 dragItemIndex 以便我们知道哪个项目被拖动.我们也许可以通过查看 DropArea 的 drag.source 属性,但是我们必须在委托中公开一个索引属性,以及 文档不鼓励在委托中存储状态.

  1. We store the dragItemIndex so that we know which item is being dragged. We might be able to achieve the same thing by looking at DropArea's drag.source property, but then we'd have to expose an index property in the delegate, and the documentation discourages storing state in delegates.

为了实现将项目放回不成功拖动的位置"功能,我们将 dragRect 设置为实际委托项目的子项,以便它有一个父项可以坚持.如果我们不这样做,该项目的父项将是 ListView,并且当不成功拖放时,它只会放在最后一次拖动的位置.

To achieve the "items get placed back where they were on unsuccessful drags" functionality, we make dragRect a child of the actual delegate item, so that it has a parent to stick to. If we didn't do this, the item's parent would be the ListView, and when unsuccessfully dropped, it would just lay where it was last dragged.

我们使用与 拖放相同的状态更改行为例子;拖动时,我们希望从项目中移除锚点并让它自由拖动.如果拖动失败,状态 (dragRect.Drag.active) 的 when 条件变为 false,并且该项目的父级返回到尚未移动的委托项目从其在列表视图中的原始位置.锚也恢复了.这是状态的一个有用特性;能够隐式恢复以前的状态.

We use the same state change behaviour as the Drag and Drop example; upon dragging we want to remove the anchors from the item and let it be dragged freely. If the drag fails, the when condition for the state (dragRect.Drag.active) becomes false, and the item is parented back to the delegate item that hasn't moved from its original place in the list view. The anchors are also restored. This is a useful feature of states; being able to implicitly restore previous state.

MouseAreadrag.onActiveChanged 信号处理程序中,我们调用 dragRect.Drag.drop() 以便我们可以在 DropAreaonDropped 信号处理程序中响应该事件,并删除该项目.删除项目后,我们将 dragItemIndex 重置为无效索引.

In the MouseArea's drag.onActiveChanged signal handler, we call dragRect.Drag.drop() so that we can respond to that event in DropArea's onDropped signal handler, and remove the item. After the item has been removed, we reset the dragItemIndex to an invalid index.

这篇关于使用 ListView 拖放来创建清单 UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆