从父节点删除节点后,Java JTree的ui刷新

时间:2014-11-24 15:30:26

标签: java jtree

当我从Jtree中删除节点时,有时其他节点的jlabel不会刷新,文本被切断,因此显示三个点" ..."因为jlabel具有已删除的上一个节点的宽度,并且UI没有按照代码中的请求进行刷新。

我相信我正确管理节点并正确刷新用户界面,但我想我或者在代码中遗漏了某些内容,或者我完全做错了。我希望有人可以帮助我。

这是我的JTree的一个例子:

RootNode
    ParentNodeA
        ChildNodeA1
        ChildNodeA2
    ParentNodeB
        ChildNodeB1_hithere
        ChildNodeB2_imlost
        ChildNodeB3_whoisthere
        ChildNodeB4_dude

说我想添加节点" ChildNodeA3"到ParentNodeA。我通过提供JTree对象和一个字符串数组来调用函数addNodeToTree(),该字符串数组包含我想要新节点的路径,即:[RootNode,ParentNodeA]。

当我想删除一个节点时,说" ChildNodeB2_imlost",我调用了函数removeNodeFromTree(tree,[RootNode,ParentNodeB,ChildNodeB2_imlost]),我提供了jtree对象和一个完整的字符串数组要删除的节点的路径。

当我删除节点时,其他节点jlabels UI不会在新位置刷新,并且仍然保持其原始宽度位于其最后位置,现在不会环绕新位置的文本,因此显示三个点。

在下面的代码中,我根据需要验证路径并扩展父节点,以便找到要删除的节点。删除节点后,我使用树模型重新加载已删除的节点的父节点以重新加载UI,但仍然无法正常工作。

public void removeNodeFromTree(JTree tree, String[] path)
{
    TreePath treepath = null;

    for (String section : path)
    {
        int row = (treepath == null ? 0 : tree.getRowForPath(treepath));

        // Expand the current tree path because it seems that if the current tree
        // path is collapsed, getNextMatch() returns null even though the node we are
        // looking for exists. Not sure if this is a bug in JTree.getNextPath() or if that is the intent.
        tree.fireTreeExpanded(treepath);
        treepath = tree.getNextMatch(section, row, Position.Bias.Forward);

        // Return if the path provided doesn't exist.
        if ( treepath == null )
        {
            return;
        }
    }

    // Get the target node to be removed.
    DefaultMutableTreeNode targetNode (DefaultMutableTreeNode)treepath.getLastPathComponent();
    // Get the parent of the target node.
    DefaultMutableTreeNode nParent = (DefaultMutableTreeNode)targetNode.getParent();

    targetNode.removeFromParent();

    // Get the tree model from the JTree object and refresh the parent node.
    DefaultTreeModel tModel = (DefaultTreeModel)tree.getModel();
    tMode.reload(nParent);
}


public void addNodeToTree(JTree tree, String[] path, Object userObject)
{
    TreePath treepath = null;

    for (String section : path)
    {
        int row = (treepath == null ? 0 : tree.getRowForPath(treepath));

        // Expand the current tree path because it seems that if the current tree
        // path is collapsed, getNextMatch() returns null even though the node we are
        // looking for exists. Not sure if this is a bug in JTree.getNextPath() or if that is the intent.
        tree.fireTreeExpanded(treepath);
        treepath = tree.getNextMatch(section, row, Position.Bias.Forward);

        // Return if the path provided doesn't exist.
        if ( treepath == null )
        {
            return;
        }
    }

    // Get the parent of the new node to be added.
    DefaultMutableTreeNode nParent = (DefaultMutableTreeNode)targetNode.getParent();
    nParent.add(new DefaultMutableTreeNode(userObject));

    // Get the tree model from the JTree object and refresh the parent node.
    DefaultTreeModel tModel = (DefaultTreeModel)tree.getModel();
    tMode.reload(nParent);
}

有什么想法吗?先谢谢你。

1 个答案:

答案 0 :(得分:1)

好的,所以在查看了trashgod提供的关于动态更改树的链接后,我意识到我之前添加和删除节点的方式不正确。我发现,使用getNextMatch()方法时,prefix参数不用于查找其值的精确匹配。它用于查找相对匹配或接近前缀值的内容。这对我来说是个大问题,因为我的节点名称相似,所以这种方法会失败,即:如果我在搜索NodeA并且NodeAB在JTree中的NodeA之前,那么我会得到NodeAB,因为前缀是&#34 ; NodeA上"和NodeAB有" NodeA"在里面。 另一个问题是我没有使用树模型来插入节点或删除JTree中的节点。似乎添加或删除节点的正确方法是通过树模型。这将在添加或删除JTree中的节点时执行正确的UI更新。

以下是我编写的新代码,它将以正确的方式添加和删除JTree中的节点:

在这段代码中我假设我有一个用户定义的对象,当调用toString()时,它将返回一个表示该对象的字符串。此用户定义的对象将添加到addNodeToTree()中的节点。

// Adds a node to a JTree providing the name of the parent node that the new node
// belongs to.
private void addNodeToTree(Object newObject, String category, JTree tree) {
    DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
    DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();

    // BreadFirst means it searches by top nodes first. It'll start with the root node,
    // then iterate thru the children of the root node and so on.
    Enumeration en = rootNode.breadthFirstEnumeration();

    while ( en.hasMoreElements() ) {
        DefaultMutableTreeNode categoryNode = (DefaultMutableTreeNode)en.nextElement();
        // Get the user defined object.
        Object categoryObject = categoryNode.getUserObject();

        // Check if node matches the category that the new node belongs to and if it does, then
        // add the new node in this category node.
        if ( categoryObject.toString().equals(category) ) {
            // Create a new node.
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newObject);
            // Use the tree model to insert the new node. This will take care of the UI updates.
            treeModel.insertNodeInto(newNode, categoryNode, categoryNode.getChildCount());
            // Exit out of the loop.
            break;
        }
    }
}

// Iterates thru all the nodes in the JTree and removes the node that
// matches the string node_name.
private void removeNodeFromTree(String node_name, JTree tree) {
    DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
    DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();

    // DepthFirst means it provides the very last child nodes and work its way up to the root node.
    Enumeration en = rootNode.depthFirstEnumeration();

    while ( en.hasMoreElements() ) {
        // Get a reference to a node in the tree to see if it is the target node.
        DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode)en.nextElement();
        // Get the virtual component object of the target node.
        Object objectTargetNode = targetNode.getUserObject();

        // If the target node matches the node_name string, then remove the node using
        // the tree model to perform the removal.
        if ( objectTargetNode.toString().equals(node_name) ) {
            treeModel.removeNodeFromParent(targetNode);
            // Exit out of the loop.
            break;
        }
    }
}

我希望这可以帮助遇到同样问题的人。