如何在QML中正确遍历访问嵌套QStandardItemModel的子项
问题根因
你在深层DelegateModel中调用modelIndex(index)时,index是当前DelegateModel内部相对于父节点的行号,而modelIndex()方法默认基于模型的根节点创建索引,导致最终指向了错误的模型节点,所以第三层数据异常。另外你所有Delegate的Item都设置了Layout.fillHeight: true,会导致不同层级的控件相互拉伸重叠,也是显示异常的诱因之一。
修复方案
方案1:直接适配现有三层结构
你可以在每一层提前存储当前节点的完整QModelIndex,下层直接引用该索引作为rootIndex,修改后的代码如下:
ColumnLayout { anchors.fill: parent Repeater { model: backend.model Item { Layout.fillWidth: true Layout.preferredHeight: childrenRect.height // 存储顶层节点的完整索引 property var topItemIndex: modelIndex(index) ColumnLayout { anchors.fill: parent Text { color: "blue" text: model.display } Repeater { model: DelegateModel { model: backend.model rootIndex: parent.topItemIndex } Item { Layout.fillWidth: true Layout.preferredHeight: childrenRect.height // 存储一级子节点的完整索引 property var subItemIndex: parent.topItemIndex.child(index, 0) ColumnLayout { anchors.fill: parent Text { color: "green" text: model.display } Repeater { model: DelegateModel { model: backend.model rootIndex: parent.subItemIndex } Text { color: "red" text: model.display } } } } } } } } }
方案2:通用递归组件(适配任意层级嵌套)
如果你的树形结构层级不固定,可以使用递归组件自动遍历所有层级,不用写死嵌套层数:
- 首先新建递归组件
TreeItem.qml:
import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQml.Models 2.15 ColumnLayout { // 外部传入的全局模型 property var rootModel // 当前层级的父节点索引,顶层传入无效索引即可 property var parentIndex // 当前层级,可用于区分颜色、设置缩进 property int level: 0 Repeater { model: DelegateModel { model: rootModel rootIndex: parentIndex } ColumnLayout { // 按层级设置缩进,更符合树形结构展示习惯 Layout.leftMargin: level * 20 Layout.fillWidth: true Layout.preferredHeight: childrenRect.height Text { // 按层级匹配颜色,层级超过3时默认黑色 color: ["blue", "green", "red"][level] || "black" text: model.display } // 递归加载子节点,只有存在子节点时才渲染 TreeItem { rootModel: parent.rootModel parentIndex: parent.parentIndex.child(index, 0) level: parent.level + 1 visible: rootModel.hasChildren(parent.parentIndex.child(index, 0)) } } } }
- 在主页面直接调用组件即可:
ColumnLayout { anchors.fill: parent TreeItem { rootModel: backend.model // 传入模型根节点的无效父索引 parentIndex: backend.model.index(-1, 0) level: 0 } }
内容的提问来源于stack exchange,提问作者scopchanov
相关产品推荐
相关产品推荐

