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

JFace TreeViewer搜索功能实现:指定列及子节点特定列高亮问题求助

解决JFace TreeViewer特定列(含子节点)高亮问题

我来帮你搞定这个TreeViewer的列高亮需求,之前的实现只处理了顶层节点的整行样式,要精准定位到「Symbol Name」列还覆盖子节点,咱们可以从这几个核心方向调整:


1. 放弃直接操作TreeItem,改用LabelProvider控制样式

TreeViewer的节点渲染逻辑是由LabelProvider负责的,直接修改TreeItem的样式会在Viewer刷新、节点更新时失效。推荐继承StyledCellLabelProvider,通过它来精准控制指定列的高亮:

public class SymbolTreeLabelProvider extends StyledCellLabelProvider {
    private String currentSearchText = "";
    // 定义你的Symbol Name列索引,比如假设是第1列
    private static final int SYMBOL_NAME_COLUMN = 1;

    // 提供方法更新搜索文本,触发Viewer刷新样式
    public void setSearchText(String searchText) {
        this.currentSearchText = searchText.toUpperCase().trim();
        if (getViewer() != null) {
            getViewer().refresh();
        }
    }

    @Override
    public void update(ViewerCell cell) {
        Object element = cell.getElement();
        // 替换成你的数据模型类型,假设模型有getSymbolName()方法
        YourTreeNodeModel node = (YourTreeNodeModel) element;
        String symbolName = node.getSymbolName().toUpperCase();
        int columnIdx = cell.getColumnIndex();

        // 仅在Symbol Name列且文本匹配时高亮
        if (columnIdx == SYMBOL_NAME_COLUMN && symbolName.contains(currentSearchText)) {
            // 方式1:整列文本变色
            cell.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
            // 方式2:高亮匹配的文本片段(更友好)
            StyledString styledStr = new StyledString(node.getSymbolName());
            int matchStart = symbolName.indexOf(currentSearchText);
            if (matchStart != -1) {
                styledStr.setStyle(matchStart, currentSearchText.length(), 
                    StyledString.DECORATIONS_STYLER); // 可自定义样式
            }
            cell.setText(styledStr);
        } else {
            // 还原默认样式
            super.update(cell);
            cell.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
        }
    }
}

2. 递归遍历所有节点,处理子节点的展开与匹配

之前的代码只遍历了顶层节点,需要写一个递归方法覆盖所有层级的子节点,确保匹配的子节点也能被展开并高亮:

private void traverseAndMatchNodes(Object element, String searchText) {
    YourTreeNodeModel node = (YourTreeNodeModel) element;
    boolean isMatch = node.getSymbolName().toUpperCase().contains(searchText.toUpperCase());

    // 匹配则展开到当前节点的所有层级
    if (isMatch) {
        viewer.expandToLevel(element, TreeViewer.ALL_LEVELS);
    }

    // 递归处理子节点
    ITreeContentProvider contentProvider = (ITreeContentProvider) viewer.getContentProvider();
    Object[] children = contentProvider.getChildren(element);
    for (Object child : children) {
        traverseAndMatchNodes(child, searchText);
    }
}

然后更新你的searchTree方法:

public void searchTree(String searchtext) {
    viewer.collapseAll();
    // 获取根节点集合(适配单根或多根场景)
    Object[] rootElements = viewer.getInput() instanceof Collection 
        ? ((Collection<?>) viewer.getInput()).toArray() 
        : new Object[]{viewer.getInput()};
    
    // 遍历所有根节点,递归检查子节点
    for (Object root : rootElements) {
        traverseAndMatchNodes(root, searchtext);
    }

    // 通知LabelProvider更新搜索文本,触发样式刷新
    ((SymbolTreeLabelProvider) viewer.getLabelProvider()).setSearchText(searchtext);
}

3. 关于SearchableTreeViewer的替代原因

SearchableTreeViewer默认是整行匹配,而且高亮逻辑封装较死,无法精准控制到单一列。自定义LabelProvider的方式更灵活,完全符合你「仅高亮Symbol Name列」的需求,同时能稳定维持样式不会失效。

内容的提问来源于stack exchange,提问作者Promod Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:57:41