我想使用 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;
}
}
}
}
此示例中需要注意的一些事项:
我们存储
dragItemIndex
,以便我们知道正在拖动哪个项目。我们也许可以通过查看 DropArea 的 drag.source 来实现同样的目标。属性,但是我们必须在委托(delegate)中公开一个索引属性,以及 documentation discourages storing state in delegates .为了实现“项目被放回不成功拖动时的位置”功能,我们将
dragRect
设为实际委托(delegate)项目的子项,以便它有一个可以坚持的父项。如果我们不这样做,该项目的父级将是 ListView,并且当未成功放置时,它只会位于上次拖动的位置。我们使用与 Drag and Drop example 相同的状态更改行为;拖动时,我们希望从项目中删除 anchor 并让它自由拖动。如果拖动失败,状态 (
dragRect.Drag.active
) 的when
条件将变为 false,并且该项目将回到尚未移动的委托(delegate)项目的父级从其在 ListView 中的原始位置。 anchor 也被恢复。这是国家的一个有用的特征;能够隐式恢复以前的状态。在
MouseArea
的drag.onActiveChanged
信号处理程序中,我们调用dragRect.Drag.drop()
以便我们可以在DropArea
的onDropped
信号处理程序中响应该事件,并删除该项目。删除项目后,我们将dragItemIndex
重置为无效索引。
关于qt - 使用 ListView 的拖放功能来创建库存 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26045587/