qt - 使用 ListView 的拖放功能来创建库存 UI

标签 qt listview drag-and-drop qml

我想使用 ListView 为我的游戏创建一个库存 UI,其中可以通过在关卡中拖放项目来将其从库存中删除。如果某个元素没有正确放置(仍在元素栏内),则应将其放回拖动前的位置。

我有以下代码,但即使在查看 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
        }
    }
}

最佳答案

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

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 来实现同样的目标。属性,但是我们必须在委托(delegate)中公开一个索引属性,以及 documentation discourages storing state in delegates .

  2. 为了实现“项目被放回不成功拖动时的位置”功能,我们将 dragRect 设为实际委托(delegate)项目的子项,以便它有一个可以坚持的父项。如果我们不这样做,该项目的父级将是 ListView,并且当未成功放置时,它只会位于上次拖动的位置。

  3. 我们使用与 Drag and Drop example 相同的状态更改行为;拖动时,我们希望从项目中删除 anchor 并让它自由拖动。如果拖动失败,状态 (dragRect.Drag.active) 的 when 条件将变为 false,并且该项目将回到尚未移动的委托(delegate)项目的父级从其在 ListView 中的原始位置。 anchor 也被恢复。这是国家的一个有用的特征;能够隐式恢复以前的状态。

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

关于qt - 使用 ListView 的拖放功能来创建库存 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26045587/

相关文章:

qt - QCheckBox 自动换行

c++ - 分布式 dll 和 c++ 对象 - 一些库如何处理这个?

android - 单击android中的基本适配器时如何更改文本颜色

android - ListView 与线性布局

Angular Material 拖放 - 不同的对象类型

c# - 拖放动态创建的快捷方式

qt - 是否有支持 CSS3 列的 wkhtmlto(pdf/image) 版本?

c++ - QML FontLoader 不工作

flutter - Flutter中的水平列表列表

javascript - html5 : dragging a tr into another table