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

查看:62
本文介绍了使用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的拖动,我们也许可以实现相同的目的.source 属性,但随后我们必须在委托中公开index属性,并

  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.

MouseArea drag.onActiveChanged 信号处理程序中,我们调用 dragRect.Drag.drop(),这样我们可以在 DropArea onDropped 信号处理程序中响应该事件,并删除该项目.删除该项目后,我们将 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天全站免登陆