我想使用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
}
}
}
答案 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;
}
}
}
}
此示例中需要注意的一些事项:
我们存储dragItemIndex
,以便我们知道正在拖动哪个项目。我们可以通过查看DropArea的drag.source属性来实现相同的功能,但是我们必须在委托中公开索引属性,并documentation discourages storing state in delegates。
为了实现“将项目放回到不成功拖动的位置”功能,我们使dragRect
成为实际委托项的子项,以便它有一个父项可以坚持。如果我们不这样做,那么项目的父项将是ListView,并且当未成功删除时,它将只是放在最后拖动的位置。
我们使用与Drag and Drop example相同的状态更改行为;在拖动时,我们想要从项目中移除锚点并让它自由拖动。如果拖动失败,则状态when
条件(dragRect.Drag.active
)将变为false,并且该项目将作为父级的父级,并且不会从列表视图中的原始位置移动。锚也恢复了。这是各州的有用特征;能够隐含地恢复以前的状态。
在MouseArea
的{{1}}信号处理程序中,我们致电drag.onActiveChanged
,以便我们可以在dragRect.Drag.drop()
的{{1}}中回复该事件信号处理程序,并删除该项目。删除该项后,我们会将DropArea
重置为无效索引。