由于qml中的TreeView属于QtQuick1.x,目前也不再进行feature上的扩展,相关的资料也不多,导致想在上面实现一些常见的操作也变得困难,比如本次想在TreeView实现从移动item到其他item上。
我们之前的文章在qml-TreeView自定义模型里的数据讲解了如何在TreeView传递自定义数据类型,本次文章仍然在这个基础上实现。
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQml.Models 2.13
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.13
import HoHai.ViewModel 1.0
Window {
id: mainWindow
visible: true
color: "black"
x: 50; y: 50
minimumWidth: 800
minimumHeight: 600
property var dragIndex
Rectangle{
width: 600
height: 800
Rectangle {
id: leftView
anchors.fill: parent
color: "white"
TreeView {
id: treeView
anchors.fill: parent
headerVisible: false
backgroundVisible: false
frameVisible: false
model: myModel
rowDelegate: Rectangle {
height: 30
color: "#303030"
}
itemDelegate: Item{
id: treeItem
DropArea {
id: dropArea
anchors.fill: parent
onDropped: {
dragRect.color = "lightgreen"
}
onEntered: {
dragRect.color = "lightblue"
}
onExited: {
dragRect.color = "transparent"
}
}
Rectangle {
id: dragRect
color: "#454545"
width: parent.width
height: 30
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Component.onCompleted: {
treeView.expand(styleData.index);
}
Text {
id: contentTex
x: 25
color: "white"
anchors.verticalCenter: parent.verticalCenter
text: styleData.value === undefined ? "" : (styleData.value.text === undefined ? "": (styleData.value.text === null ? "" : styleData.value.text))
}
MouseArea{
id:rowMouseArea
anchors.fill: parent
hoverEnabled: true
property bool hovered : false
acceptedButtons: Qt.LeftButton | Qt.RightButton
drag.target: dragRect
drag.onActiveChanged: {
if (rowMouseArea.drag.active) {
dragIndex = styleData.index;
}
dragRect.Drag.drop();
}
}
states: [
State {
when: dragRect.Drag.active
ParentChange {
target: dragRect
parent: treeView; width: dragRect.width; height: dragRect.height
}
AnchorChanges {
target: dragRect
anchors.horizontalCenter: undefined
anchors.verticalCenter: undefined
}
}
]
Drag.active: rowMouseArea.drag.active
Drag.supportedActions: Qt.CopyAction;
Drag.hotSpot.x: dragRect.width / 2
Drag.hotSpot.y: dragRect.height / 2
}
}
TableViewColumn {
role: "type"
title: "Name"
width: 800 //列的宽//会影响drag事件
}
}
}
}
}
- Qml的Drag&&Drop事件主要封装在DropArea,当其他项(文件,文件夹等)被拖动到它上面时,它将接收到事件。有几个信号需要注意一下:
1)onEntered为拖拽到(鼠标进入)控件触发事件;
2)onExited为拖拽到(鼠标离开)控件出发事件;
3)onDropped为拖拽到控件后(鼠标松手后)触发事件;
drag和drop分别为onEntered和onDropped事件可捕抓到的内容; - drag的事件要从MouseArea捕捉
1)drag.target 拖拽生效的目标
2)drag.onActiveChanged 是拖拽激发的时候出发的信号,这里将拖拽的item-index保存起来 - drag时item的跟随鼠标移动是通过states来实现,关于ParentChange和AnchorChanges可以从Qt的帮助文档查到,文档里有简单的介绍,这里不再展开
- 最后有个需要注意的是需要设置TableViewColumn的宽度,要不然不能出发drag松开到达某个item时的出发事件(也即onDropped事件)
DragItemInTreeView.gif