FilteredTree (JFace):显示所有子项的自定义过滤器

发布于 2024-09-26 08:56:51 字数 305 浏览 0 评论 0原文

我目前正在使用带有 PatternFilter 的 FilteredTree 在树中显示数据。
我的问题是它只显示与模式匹配的元素并隐藏它们的子元素(除非它们也与模式匹配)。

示例:
树:

A
-B
--1
--2
-C
--1
--2

模式“B”给我:

A
-B

但我需要:

A
-B
--1
--2

我尝试了一些方法,但没有找到一个好的/简单的方法来做到这一点。 有什么想法吗?

I'm currently using a FilteredTree with a PatternFilter to display data in a Tree.
My problem is that it only shows the elements matching the pattern and hides their children (except they also match the pattern).

Example:
Tree:

A
-B
--1
--2
-C
--1
--2

Pattern "B" gives me:

A
-B

But I need:

A
-B
--1
--2

I tried a few things but didn't find a nice/easy way to do this.
Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

緦唸λ蓇 2024-10-03 08:56:51

这是默认行为。重写 PatternFilter.isParentMatch() 和 PatternFilter.isLeafMatch() 以获得正确的结果。

Thats the default behaviour. Override the PatternFilter.isParentMatch() and PatternFilter.isLeafMatch() to get the right results.

饮惑 2024-10-03 08:56:51

我遇到了同样的问题:元素被正确过滤,但没有显示树节点的子节点。用户必须选择找到的节点(希望这只是一个结果),然后重置过滤器并查看选择与子节点一起出现的位置。

解决这个问题需要覆盖 PatternFilter#isLeafMatch() 并使用 JavaReflection 从 PatternFilter 检索(私有)字段 cache

public class MyPatternFilter extends PatternFilter {

    private final Map<Object, Object> patternFilterCache;

    public MyPatternFilter () {
        this.patternFilterCache = getCache();
    }

    @Override
    protected boolean isLeafMatch(final Viewer viewer, final Object element) {
        boolean result = super.isLeafMatch(viewer, element);
        if (result) { // element matches, now add all its children
            traverseChildren(((MyTreeNode) element).getChildren());
        }
        return result;
    }

    // this is to traverse the children of the element found before
    // these children need to be added to the Map 'cache' to be displayed
    void traverseChildren(List<MyTreeNode> children) {  
        // assuming that child.getChildren() is never null!
        for(MyTreeNode child : children) {
            this.patternFilterCache.put(child, child.getChildren().stream().toArray(MyTreeNode[]::new));
            traverseChildren(child.getChildren());
        }
    }

    private Map<Object, Object> getCache() {
        try {
            Field cacheField = this.getClass().getSuperclass().getDeclaredField("cache"); //$NON-NLS-1$
            cacheField.setAccessible(true);
            @SuppressWarnings("unchecked")
            Map<Object, Object> cache = (Map<Object, Object>) cacheField.get(this);
            cacheField.setAccessible(false);
            return cache;
        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

}

明显的缺点是地图“缓存”不是 API,因此从理论上讲,如果名称更改,此解决方案将失败。

I had the same problem: The element was filtered correctly but no children of the tree node were displayed. The user had to select the found node (in hope it was only one result) then reset the filter and look where the selection appeared along with the children.

Solving this requires overwriting of PatternFilter#isLeafMatch() and retrieving of the (private) field cache from PatternFilter with JavaReflection:

public class MyPatternFilter extends PatternFilter {

    private final Map<Object, Object> patternFilterCache;

    public MyPatternFilter () {
        this.patternFilterCache = getCache();
    }

    @Override
    protected boolean isLeafMatch(final Viewer viewer, final Object element) {
        boolean result = super.isLeafMatch(viewer, element);
        if (result) { // element matches, now add all its children
            traverseChildren(((MyTreeNode) element).getChildren());
        }
        return result;
    }

    // this is to traverse the children of the element found before
    // these children need to be added to the Map 'cache' to be displayed
    void traverseChildren(List<MyTreeNode> children) {  
        // assuming that child.getChildren() is never null!
        for(MyTreeNode child : children) {
            this.patternFilterCache.put(child, child.getChildren().stream().toArray(MyTreeNode[]::new));
            traverseChildren(child.getChildren());
        }
    }

    private Map<Object, Object> getCache() {
        try {
            Field cacheField = this.getClass().getSuperclass().getDeclaredField("cache"); //$NON-NLS-1$
            cacheField.setAccessible(true);
            @SuppressWarnings("unchecked")
            Map<Object, Object> cache = (Map<Object, Object>) cacheField.get(this);
            cacheField.setAccessible(false);
            return cache;
        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

}

The obvious drawback is that the Map 'cache' is not API, so - in theory - if the name changes this solution will fail.

热鲨 2024-10-03 08:56:51

发布我的第一个答案感觉真好!

重写 isElementVisible() 并添加返回条件。

public class FilePatternFilter extends PatternFilter {
    @Override
    public boolean isElementVisible(Viewer viewer, Object element) {
        File file = (File) element;
        return isParentMatch(viewer, element) || isLeafMatch(viewer, element) || isLeafMatch(viewer, file.getParent());
    }
}

It feels so good to post my first answer!

Override isElementVisible() and add return condition.

public class FilePatternFilter extends PatternFilter {
    @Override
    public boolean isElementVisible(Viewer viewer, Object element) {
        File file = (File) element;
        return isParentMatch(viewer, element) || isLeafMatch(viewer, element) || isLeafMatch(viewer, file.getParent());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文