Hello. I'm trying to create a tree that is responsive when there are 1000's of items in it (and is always expanded). I have used this as a start point, but the repeater means that it is slow and unresponsive. I want to swap the repeater for a ListView, but if I just do a straight swap, the list is drawn over the top of the parent instead of underneath it, and subsequent items in the list are drawn over each other. The parent item sizes like I want it to, but if you just run the code in qmlscene and do the following:
Add Node-> node0
Add Node-> 0,n1
Add Node-> 0,n2
You can see that subchildren are not being drawn in the correct spot. I believe it's some interaction between the Column and the ListView, but I'm too much of a noob to be able to work out a solution. Can you please help. Full code is below, the ListView with ID objRepeater is what I'm trying to get working:
Qt Code:
  1. import QtQuick 2.0
  2. import QtQuick.Window 2.0
  3. import QtQuick.Layouts 1.0
  4. import QtQuick.Controls 1.0
  5. Rectangle {
  6. id: objRoot
  7. objectName: "objRoot"
  8. width: 600
  9. height: 600
  10. color: "black"
  11. ListModel {
  12. id: objModel
  13. objectName: "objModel"
  14. }
  15. Component {
  16. id: objRecursiveDelegate
  17. Item {
  18. Column {
  19. id: objRecursiveColumn
  20. objectName: "objRecursiveColumn"
  21. property int m_iIndex: model.index
  22. property var m_parentModel: model.parentModel
  23. clip: true
  24. MouseArea {
  25. id: objMouseArea
  26. objectName: "objMouseArea"
  27. width: objRow.implicitWidth
  28. height: objRow.implicitHeight
  29. onDoubleClicked: {
  30. for(var i = 0; i < parent.children.length; ++i) {
  31. if(parent.children[i].objectName !== "objMouseArea") {
  32. parent.children[i].visible = !parent.children[i].visible
  33. }
  34. }
  35. }
  36. drag.target: objDragRect
  37. onReleased: {
  38. if(objDragRect.Drag.target) {
  39. objDragRect.Drag.drop()
  40. }
  41. }
  42. Row {
  43. id: objRow
  44. Item {
  45. id: objIndentation
  46. height: 20
  47. width: model.level * 20
  48. }
  49. Rectangle {
  50. id: objDisplayRowRect
  51. height: objNodeName.implicitHeight + objRepeater.contentHeight + 5
  52. width: objCollapsedStateIndicator.width + objNodeName.implicitWidth + 5
  53. border.color: "green"
  54. border.width: 2
  55. color: "#31312c"
  56. DropArea {
  57. keys: [model.parentModel]
  58. anchors.fill: parent
  59. onEntered: objValidDropIndicator.visible = true
  60. onExited: objValidDropIndicator.visible = false
  61. onDropped: {
  62. objValidDropIndicator.visible = false
  63. if(drag.source.m_objTopParent.m_iIndex !== model.index) {
  64. objRecursiveColumn.m_parentModel.move(
  65. drag.source.m_objTopParent.m_iIndex,
  66. model.index,
  67. 1
  68. )
  69. }
  70. }
  71. Rectangle {
  72. id: objValidDropIndicator
  73. anchors.fill: parent
  74. visible: false
  75. onVisibleChanged: {
  76. visible ? objAnim.start() : objAnim.stop()
  77. }
  78. SequentialAnimation on color {
  79. id: objAnim
  80. loops: Animation.Infinite
  81. running: false
  82. ColorAnimation { from: "#31312c"; to: "green"; duration: 400 }
  83. ColorAnimation { from: "green"; to: "#31312c"; duration: 400 }
  84. }
  85. }
  86. }
  87. Rectangle {
  88. id: objDragRect
  89. property var m_objTopParent: objRecursiveColumn
  90. Drag.active: objMouseArea.drag.active
  91. Drag.keys: [model.parentModel]
  92. border.color: "magenta"
  93. border.width: 2
  94. opacity: .85
  95. states: State {
  96. when: objMouseArea.drag.active
  97. AnchorChanges {
  98. target: objDragRect
  99. anchors { horizontalCenter: undefined; verticalCenter: undefined }
  100. }
  101. ParentChange {
  102. target: objDragRect
  103. parent: objRoot
  104. }
  105. }
  106. anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter }
  107. height: objDisplayRowRect.height
  108. width: objDisplayRowRect.width
  109. visible: Drag.active
  110. color: "red"
  111. Text {
  112. anchors.left: parent.left
  113. height: 20
  114. //horizontalAlignment: Text.AlignHCenter
  115. //verticalAlignment: Text.AlignVCenter
  116. text: model.name
  117. font { bold: true; pixelSize: 18 }
  118. color: "blue"
  119. }
  120. }
  121. Text {
  122. id: objCollapsedStateIndicator
  123. anchors { left: parent.left; top: parent.top;}// bottom: parent.bottom }
  124. width: 20
  125. height: 20
  126. //horizontalAlignment: Text.AlignHCenter
  127. //verticalAlignment: Text.AlignVCenter
  128. text: "+"//objRepeater.count > 0 ? objRepeater.visible ? qsTr("-") : qsTr("+") : qsTr("")
  129. font { bold: true; pixelSize: 18}
  130. color: "yellow"
  131. }
  132. Text {
  133. id: objNodeName
  134. anchors { left: objCollapsedStateIndicator.right; top: parent.top; }//bottom: parent.bottom }
  135. text: model.name
  136. height: 20
  137. color: "yellow"//objRepeater.count > 0 ? "yellow" : "white"
  138. font { bold: true; pixelSize: 18 }
  139. //verticalAlignment: Text.AlignVCenter
  140. }
  141. }
  142. }
  143. }
  144. Rectangle {
  145. id: objSeparator
  146. anchors { left: parent.left; right: parent.right; }
  147. height: 1
  148. color: "black"
  149. }
  150. ListView {
  151. anchors {top: objRecursiveColumn.bottom; left: parent.left; right: parent.right; bottom:parent.bottom;}
  152. //contentHeight: contentItem.childrenRect.height
  153. id: objRepeater
  154. objectName: "objRepeater"
  155. model: subNode
  156. delegate: objRecursiveDelegate
  157. }
  158. }
  159. }
  160. ColumnLayout {
  161. objectName: "objColLayout"
  162. anchors.fill: parent
  163. ScrollView {
  164. Layout.fillHeight: true
  165. Layout.fillWidth: true
  166. ListView {
  167. objectName: "objListView"
  168. model: objModel
  169. delegate: objRecursiveDelegate
  170. interactive: false
  171. }
  172. }
  173. Window {
  174. id: objModalInput
  175. objectName: "objModalInput"
  176. modality: Qt.ApplicationModal
  177. visible: false
  178. height: 30
  179. width: 200
  180. color: "yellow"
  181. TextInput {
  182. anchors.fill: parent
  183. font { bold: true; pixelSize: 20 }
  184. verticalAlignment: TextInput.AlignVCenter
  185. horizontalAlignment: TextInput.AlignHCenter
  186. validator: RegExpValidator {
  187. regExp: /(\d{1,},)*.{1,}/
  188. }
  189. onFocusChanged: {
  190. if(focus) {
  191. selectAll()
  192. }
  193. }
  194. text: qsTr("node0")
  195. onAccepted: {
  196. if(acceptableInput) {
  197. objModalInput.close()
  198. var szSplit = text.split(',')
  199. if(szSplit.length === 1) {
  200. objModel.append({"name": szSplit[0], "level": 0, "parentModel": objModel, "subNode": []})
  201. }
  202. else {
  203. if(objModel.get(parseInt(szSplit[0])) === undefined) {
  204. console.log("Error - Given node does not exist !")
  205. return
  206. }
  207. var node = objModel.get(parseInt(szSplit[0]))
  208. for(var i = 1; i < szSplit.length - 1; ++i) {
  209. if(node.subNode.get(parseInt(szSplit[i])) === undefined) {
  210. console.log("Error - Given node does not exist !")
  211. return
  212. }
  213. node = node.subNode.get(parseInt(szSplit[i]))
  214. }
  215. node.subNode.append({"name": szSplit[i], "level": i, "parentModel": node.subNode, "subNode": []})
  216. }
  217. }
  218. }
  219. }
  220. }
  221. Button {
  222. text: "add data to tree"
  223. onClicked: {
  224. objModalInput.show()
  225. }
  226. }
  227. }
  228. }
To copy to clipboard, switch view to plain text mode