qml并没有提供树控件,只能自己写了。model仍然用ListModel对象,弄成层级的就行。delegate必须用loader动态的增加子控件,如此而已。
【先看效果】
【下载】
http://download.csdn.net/detail/surfsky/8406181
【核心代码】
1 import QtQuick 2.1 2 import QtQuick.Controls 1.0 3 4 5 /** 6 树控件 7 作者:surfsky.cnblogs.com 2014-10 8 协议:MIT 请保留本文档说明 9 功能 10 /递归树显示 11 /左侧一个箭头,点击可展开显示子树 12 /选中节点变色 13 /节点点击事件 14 /tag属性,携带类似id的数据 15 异步方式,点击箭头后请求子数据。异步模式的话,节点要加上isLeaf属性,点击箭头后动态加载数据 16 使用 17 TreeView { 18 anchors.fill: parent 19 id: tree 20 model: modelTree2 21 onSelectedItemChanged: console.log(item.text) 22 } 23 ListModel { 24 id: modelTree2 25 Component.onCompleted: { 26 modelTree2.append([ 27 {title: "Node 1"}, 28 {title: "Node 2", items: [ 29 {title: "Node 21", items:[ 30 {title: "Node 211"}, 31 {title: "Node 212"} 32 ]}, 33 {title: "Node 22"} 34 ] 35 }, 36 {title: "Node 3"} 37 ]); 38 } 39 } 40 参考 http://qt-project.org/forums/viewthread/30521/ 41 */ 42 ScrollView { 43 id: view 44 frameVisible: true 45 implicitWidth: 200 46 implicitHeight: 160 47 48 // 输入属性 49 property var model 50 property int rowHeight: 19 51 property int columnIndent: 22 52 property string expanderImage : "expander.png"; 53 54 // 私有属性 55 property var currentNode // 当前节点数据 56 property var currentItem // 当前节点UI 57 58 // 信号 59 signal selectedItemChanged(var item) 60 61 62 // 节点数据展示的UI 63 property Component delegate: Label { 64 id: label 65 text: model.title ? model.title : 0 66 color: currentNode === model ? "white" : "black" 67 property var tag : model.tag 68 } 69 70 // 71 contentItem: Loader { 72 id: content 73 onLoaded: item.isRoot = true 74 sourceComponent: treeBranch 75 property var items: model 76 77 // 背景条纹 78 Column { 79 anchors.fill: parent 80 Repeater { 81 model: 1 + Math.max(view.contentItem.height, view.height) / rowHeight 82 Rectangle { 83 objectName: "Faen" 84 color: index % 2 ? "#eee" : "white" 85 width: view.width ; height: rowHeight 86 } 87 } 88 } 89 90 // 树节点组件 91 Component { 92 id: treeBranch 93 Item { 94 id: root 95 property bool isRoot: false 96 implicitHeight: column.implicitHeight 97 implicitWidth: column.implicitWidth 98 Column { 99 id: column 100 x: 2 101 Item { height: isRoot ? 0 : rowHeight; width: 1} 102 Repeater { 103 model: items 104 Item { 105 id: filler 106 width: Math.max(loader.width + columnIndent, row.width) 107 height: Math.max(row.height, loader.height) 108 property var _model: model 109 // 当前行背景色块 110 Rectangle { 111 id: rowfill 112 x: view.mapToItem(rowfill, 0, 0).x 113 width: view.width 114 height: rowHeight 115 visible: currentNode === model 116 color: "#37f" 117 } 118 // 行点击响应区域 119 MouseArea { 120 anchors.fill: rowfill 121 onPressed: { 122 currentNode = model 123 currentItem = loader 124 forceActiveFocus() 125 selectedItemChanged(model); 126 } 127 } 128 // 行数据UI 129 Row { 130 id: row 131 // 行图标 132 Item { 133 width: rowHeight 134 height: rowHeight 135 opacity: !!model.items ? 1 : 0 136 Image { 137 id: expander 138 source: view.expanderImage 139 height: view.rowHeight * 0.6 140 fillMode: Image.PreserveAspectFit 141 opacity: mouse.containsMouse ? 1 : 0.7 142 anchors.centerIn: parent 143 rotation: loader.expanded ? 90 : 0 144 Behavior on rotation {NumberAnimation { duration: 120}} 145 } 146 MouseArea { 147 id: mouse 148 anchors.fill: parent 149 hoverEnabled: true 150 onClicked: loader.expanded = !loader.expanded 151 } 152 } 153 // 行文本 154 Loader { 155 property var model: _model 156 sourceComponent: delegate 157 anchors.verticalCenter: parent.verticalCenter 158 } 159 } 160 161 // 子树(递归自身) 162 Loader { 163 id: loader 164 x: columnIndent 165 height: expanded ? implicitHeight : 0 166 property var node: model 167 property bool expanded: false 168 property var items: model.items 169 property var text: model.title 170 sourceComponent: (expanded && !!model.items) ? treeBranch : undefined 171 } 172 } 173 } 174 } 175 } 176 } 177 } 178 }
时间: 2024-10-22 21:27:23