【问题标题】:Why does node selection not work properly after TreeModel reload?为什么 TreeModel 重新加载后节点选择无法正常工作?
【发布时间】:2017-02-24 16:56:59
【问题描述】:

我有一个使用 JTree 的 Swing 应用程序。我希望隐藏树的一些节点,所以我实现了两个DefaultTreeModels,一个包含每个节点,一个过滤后的只包含应该显示的节点。后者设置为实际模型。

在某些时候我必须更改过滤的节点,当我这样做时,树中的项目会正确更新,但它们的行为是错误的。 节点在被选中时不会突出显示(即使它们确实被选中)并且用户不能再双击展开节点,他们必须点击小“+”按钮。 p>

下面是我的代码的概括,我的自定义类中的两个方法扩展了JTree

updateFilter 在过滤器需要更新时被调用。 populateFilteredNode 递归填充我的过滤模型的根节点。为简单起见,filteredRoot 是一个类成员变量(DefaultMutableTreeNode 类型)并且是过滤模型的根。 fullModelfilteredModel 的类型为 DefaultTreeModel

public void updateFilter() {
    // Get current expansion state
    ArrayList<Integer> expansionState = getExpansionState();

    DefaultMutableTreeNode fullModelRoot = fullModel.getRoot();

    // Remove existing nodes in the filtered model
    while(filteredRoot.getChildCount() > 0) {
        filteredModel.removeNodeFromParent(filteredRoot.getFirstChild());
    }

    populateFilteredNode(fullModelRoot, filteredRoot);

    // Repaint tree and restore expansion state
    repaint();
    setExpansionState(expansionState);
}

private void populateFilteredNode(DefaultMutableTreeNode fullNode, DefaultMutableTreeNode filteredNode) {

    int index = 0;

    for(int n = 0; n < fullNode.getChildCount(); n++) {
        DefaultMutableTreeNode fullChildNode = fullNode.getChildAt(n);

        // Show the item and its children if one of many cases is true
        if(shouldShowItem(fullChildNode.getItem())) {
            DefaultMutableTreeNode filteredChildNode = fullChildNode.clone();

            filteredModel.insertNodeInto(filteredChildNode, filteredNode, index++);

            populateFilteredNode(fullChildNode, filteredChildNode);
        }
    }
}

如果有人有类似经历或知道为什么所选节点不会突出显示,请告诉我。或者如果有更好的方法来完成过滤。或者,如果更多代码有助于提供答案。

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 minimal reproducible exampleShort, Self Contained, Correct Example。 2) "..my custom class that extends JTree." 我认为这不是扩展JTree的可能性是100比1。
  • @Andrew 我承认我是新手,所以我不知道什么时候应该或不应该创建自定义子类。为什么你敢打赌这不是扩展JTree 的情况?这是否与所选节点不突出显示的原因有关?
  • 我看代码就知道了。有 MCVE/SSCCE 后我再看代码。

标签: java swing jtree treenode defaulttreemodel


【解决方案1】:

我找到了适合我的情况的东西,虽然它又快又脏,而且我不一定明白它为什么会起作用。 This 12-year-old post 在 Code Ranch 上不知何故让我朝着正确的方向前进。我只是在这里发布它,以防万一有人遇到类似的问题,它可能会有所帮助。

我在对表格模型进行任何更改之前保存选择路径,然后在进行更改后调用这个新函数findNewSelectionPath。下面是该函数的通用版本(我使用了几个自定义类,所以我尽我所能使它看起来通用)。

private TreePath findNewSelectionPath(TreePath oldSelectionPath) {
    TreePath newSelectionPath = null;

    if(oldSelectionPath != null) {
        Object[] oldPathComponents = oldSelectionPath.getPath();
        Object[] newPathComponents = new Object[oldPathComponents.length];

        DefaultMutableTreeNode node = (DefaultMutableTreeNode) filteredModel.getRoot();

        // Set the root
        if(oldPathComponents[0].equals(node)) {
            newPathComponents[0] = node;
        }

        // Set the rest of the path components
        for(int n = 1; n < oldPathComponents.length; n++) {
            for(int k = 0; k < node.getChildCount(); k++) {
                if(oldPathComponents[n].equals(node.getChildAt(k))) {
                    newPathComponents[n] = node.getChildAt(k);
                    node = node.getChildAt(k);
                    break;
                }
            }
        }

        // Make sure that the last path component exists
        if(newPathComponents[newPathComponents.length - 1] != null) {
            newSelectionPath = new TreePath(newPathComponents);
        }
    }
    return newSelectionPath;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    相关资源
    最近更新 更多