如何为自定义QML TreeView实现展开/收起全部及按ID展开路径功能
自定义QML树形组件功能实现
针对你的QML树形组件,以下是两个需求的解决方案:
1. 实现展开全部(expandAll)和收起全部(collapseAll)
核心思路是递归遍历当前层级的所有节点,修改展开状态并触发对应操作,同时递归处理子层级的树形组件(Loader加载的AppTreeView)。
修改AppTreeView.qml中的expandAll和collapseAll函数:
function expandAll() { // 遍历当前Repeater的所有delegate for (let i = 0; i < repeater.count; i++) { let delegate = repeater.itemAt(i); if (delegate && delegate.button.visible) { // 仅处理有子节点的节点 if (!delegate.isChecked) { delegate.isChecked = true; delegate.expand(delegate.modelData.nodes); } // 递归处理子层级的AppTreeView if (delegate.loader.item && delegate.loader.item.expandAll) { delegate.loader.item.expandAll(); } } } } function collapseAll() { // 遍历当前Repeater的所有delegate for (let i = 0; i < repeater.count; i++) { let delegate = repeater.itemAt(i); if (delegate && delegate.isChecked) { delegate.isChecked = false; delegate.collapse(); } // 递归处理子层级的AppTreeView if (delegate.loader.item && delegate.loader.item.collapseAll) { delegate.loader.item.collapseAll(); } } }
2. 实现按节点ID展开所有父节点
需要先构建ID到父ID的映射表,递归获取目标节点的所有父节点路径,再遍历树形组件找到这些节点并展开。
步骤1:在TreeView.qml中添加映射与路径获取函数
在TreeView.qml的Item中添加以下内容:
// 存储ID到父ID的映射 property var idToParentId: {} // 初始化映射表 function initIdParentMap() { idToParentId = {}; for (let i = 0; i < dataModel.count; i++) { let item = dataModel.get(i); idToParentId[item[dataId]] = item[dataParentId]; } } // 获取目标节点的所有父节点ID路径(从根到目标的顺序) function getParentPath(targetId) { let path = []; let currentId = targetId; while (currentId !== 0) { // 0为根节点的父ID let parentId = idToParentId[currentId]; if (parentId === undefined || parentId === 0) break; path.unshift(parentId); currentId = parentId; } path.push(targetId); // 加入目标节点自身 return path; } // 对外暴露的展开指定ID节点路径的函数 function expandNodeById(targetId) { let path = getParentPath(targetId); appTreeView.expandPath(path); }
在Component.onCompleted中初始化映射表:
Component.onCompleted: { initIdParentMap(); // 新增该行 for (let i = 0; i < dataModel.count; i++) { let item = dataModel.get(i); insertRecord(item[dataId], item[dataName], item[dataParentId]); } let m = selectRecursive(0); appTreeView.model = m; }
步骤2:在AppTreeView.qml中添加路径展开函数
在AppTreeView.qml的Column中添加:
// 递归查找并展开指定路径的节点 function expandPath(path) { if (path.length === 0) return; let targetId = path[0]; // 遍历当前层级节点 for (let i = 0; i < repeater.count; i++) { let delegate = repeater.itemAt(i); if (delegate && delegate.modelData.id === targetId) { // 展开当前节点 if (!delegate.isChecked) { delegate.isChecked = true; delegate.expand(delegate.modelData.nodes); } // 递归处理剩余路径 if (path.length > 1 && delegate.loader.item && delegate.loader.item.expandPath) { delegate.loader.item.expandPath(path.slice(1)); } break; } } }
使用示例
在main.qml中可通过按钮触发展开:
Button { text: "展开Amazon FR(ID:5)" onClicked: { customerTreeView.expandNodeById(5); } }
内容的提问来源于stack exchange,提问作者kixrogu
相关产品推荐
相关产品推荐

