You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:12:33