由於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事件)