更改JTree中的节点名称

时间:2011-02-25 18:28:54

标签: java swing jtree

我正在尝试更改JTree中节点的名称。我使用以下代码来执行此操作:


    /**
     * Change the name of the currently selected node
     * @param newName Name to change the node too
     */
    public void changeNodeName(String newName) {
        //get the path to the selected nod
        TreePath selectedPath = mainWindow.getStructureTree().getSelectionPath() ;
        //make sure there is no other node with this name
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectedPath.getLastPathComponent();
        //change its name
        node.setUserObject(newName);
}

此代码可以正常工作。所以说我想将下面图片中的节点b重命名为c。代码正确完成,如图所示。

enter image description here enter image description here

但是,如果我然后拖动节点并将其放在树中的其他位置,则其名称将返回到原始名称b。

enter image description here enter image description here

所以显然我在这里没有正确改变一些东西。我如何更改或更改以便节点值保持更改?

由于

编辑:

我有一个扩展DefaultMutableTreeNode的类。这是来源


package Structure;

import GUI.Window;
import Logging.LogRunner;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

/**
 * This class provides the basic functionality that all subclass of the structre
 * will need such as a pop up menu, and adding new nodes.
 * @author dvargo
 */
public abstract class BCStructure extends DefaultMutableTreeNode
{
    /**
     * The root node to which this class belongs
     */
    DefaultMutableTreeNode root;
    /**
     * Reference to the main window
     */
    Window mainWindow;
    /**
     * Name of this node
     */
    String name;
    /**
     * The pop up menu
     */
    JPopupMenu Pmenu;
    /**
     * The pop up menu intems
     */
    JMenuItem deleteMenuItem,renameMenuItem,newSectionMenuItem,newPageMenuItem;

    /**
     * What type of node this is
     */
    String type;

    /**
     * Basic constructor that adds a pop up menu, sets the name, and initalizes values
     * @param newName - Name for this node
     * @param inWindow - Reference to the main window.
     */
    public BCStructure(String newName,Window inWindow)
    {
        this(newName,inWindow,true);      
    }

    /**
     * Returns the type of node this is
     * @return Page if the node is a page, Module if the node is a module, Section
     * if the node is a section
     */
    public String getType()
    {
        return type;
    }


    /**
     * Returns a copy of this node
     * @return
     */
    public abstract BCStructure copy();

    /**
     * If this is a page, this constructor should be called, it will not allof a page to
     *have any children
     * @param newName - Name for the page
     * @param inWindow - Refernce to the main window
     * @param letChildren - False to disallow this node from having children
     */
    public BCStructure(String newName,Window inWindow,boolean letChildren)
    {
        super(newName,letChildren);
        mainWindow = inWindow;
        name = newName;
        //add the popup menu
        addPopUp();
    }



    /**
     * Updates a specific node
     * @param parentNode The parent node to update
     */
    public void update(DefaultMutableTreeNode parentNode)
    {
        ((DefaultTreeModel)mainWindow.getStructureTree().getModel()).reload(parentNode);
        mainWindow.getStructureTree().repaint();

    }

    /**
     * Returns the node that is currently selected (by being clicked on) in the tree
     * @return Node that is selected in the tree
     */
    public DefaultMutableTreeNode getSelectedNode()
    {
        return (DefaultMutableTreeNode)mainWindow.getStructureTree().getLastSelectedPathComponent();
    }

    /**
     * Returns the TreePath to this node
     * @return The TreePath to this node
     */
    public TreePath getTreePath()
    {
        return new TreePath(this.getPath());
    }

    /**
     * Sets the selected node in the tree
     * @param node The node to set selected in the tree
     */
    public void setSelectedNode(BCStructure node)
    {
        mainWindow.getStructureTree().setSelectionPath(new TreePath(node.getPath()));
        update(node);
    }

    /**
     * Change the name of the currently selected node
     * @param newName Name to change the node too
     */
    public void changeNodeName(String newName) {
        //get the path to the selected nod
        TreePath selectedPath = mainWindow.getStructureTree().getSelectionPath() ;
        //make sure there is no other node with this name
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectedPath.getLastPathComponent();
        DefaultMutableTreeNode nodeParent = (DefaultMutableTreeNode) node.getParent();
        if(nodeParent != null)
        {
            for(int i = 0; i lt nodeParent.getChildCount(); i++)
            {
                DefaultMutableTreeNode currNode = (DefaultMutableTreeNode) nodeParent.getChildAt(i);
                if(currNode.getUserObject().equals(newName))
                {
                    JOptionPane.showMessageDialog(mainWindow,"Another page or section already has this name in this level. Please select another.");
                    return;
                }
            }
        }
        //change its name
        node.setUserObject(newName);
        //mainWindow.getStructureTree().getModel().valueForPathChanged(selectedPath, newName);



        update(getSelectedNode());
    }

    /**
     * Adds a new section node to the tree
     * @param newName Name for this node
     */
    public void addNewSectionNode(String newName) {


        DefaultMutableTreeNode temp = getSelectedNode();
        Section newNode = null;
        if(temp == null)
        {
            LogRunner.dialogMessage(this.getClass(),"Please select a node to add this section to.");
        }

        else
        {
            newNode = new Section(newName,mainWindow);
            try
            {
                temp.add(newNode);
            }
            catch(java.lang.IllegalStateException e)
            {
                LogRunner.getLogger().warning("You can not add a section to a page");
                temp = (DefaultMutableTreeNode) temp.getParent();
                temp.add(newNode);
            }
        }
        //set the selected node to the previously selected node

        update(temp);

        if(newNode != null)
        {
            mainWindow.getStructureTree().setSelectionPath(new TreePath(newNode.getPath()));

        }
    }

    /**
     * Adds a new page to this tree
     * @param newName Name for the node
     * @return The newly created page
     */
    public Page addNewPageNode(String newName)
    {

        TreePath oldPath = mainWindow.getStructureTree().getSelectionPath();
        //Section newSection = new Section(newSectionName);
        DefaultMutableTreeNode temp = getSelectedNode();
        Page newPage = null;
        if(temp == null)
        {
            LogRunner.dialogMessage(this.getClass(),"Please select a module or section to add this section to.");
        }

        else
        {
            newPage = new Page(newName,mainWindow);
            try
            {
                temp.add(newPage);

            }
            catch(java.lang.IllegalStateException e)
            {
                LogRunner.getLogger().warning("You can not add any more nodes to a page.");
                temp = (DefaultMutableTreeNode) temp.getParent();
                temp.add(newPage);

            }
        }
        update(temp);
        mainWindow.getStructureTree().setSelectionPath(oldPath);
        return newPage;
    }


    /**
     * Propmpts the user to entere a new name for a node that is selected
     */
    private void rename()
    {
        String newname = JOptionPane.showInputDialog("New name?");
        changeNodeName(newname);
    }
    /**
     * Deletes the selected node from the tree
     */
    private void delete()
    {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)mainWindow.getStructureTree().getLastSelectedPathComponent();
        if(node == null) return;

        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode)(node.getParent());
        if(parentNode == null) return;

        //remove node
        parentNode.remove(node);
        ((DefaultTreeModel)mainWindow.getStructureTree().getModel()).reload(parentNode);
    }

    /**
     * Deletes a specific node from the tree
     * @param node The node to delete
     */
    protected void delete(DefaultMutableTreeNode node)
    {
         if(node == null) return;

        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode)(node.getParent());
        if(parentNode == null) return;

        //remove node
        parentNode.remove(node);
        ((DefaultTreeModel)mainWindow.getStructureTree().getModel()).reload(parentNode);
    }


    /**
     * Adds the popup menu functionality to the tree
     */
    private void addPopUp()
    {

        Pmenu = new JPopupMenu();
        newSectionMenuItem = new JMenuItem("Add New Section");
        Pmenu.add(newSectionMenuItem);
        newPageMenuItem = new JMenuItem("Add New Page");
        Pmenu.add(newPageMenuItem);
        Pmenu.add(new JSeparator());
        deleteMenuItem = new JMenuItem("Delete");
        Pmenu.add(deleteMenuItem);
        renameMenuItem = new JMenuItem("Rename");
        Pmenu.add(renameMenuItem);


        //add actionlisteners to the menu items
        deleteMenuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                delete();}
            }
        );

        renameMenuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                rename();}
            }
        );

        newSectionMenuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                mainWindow.createNewSectionPublicCall();}
            }
        );

        newPageMenuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                mainWindow.createNewPagePublicCall();}
            }
        );

        //add action listener to the tree
        mainWindow.getStructureTree().addMouseListener(new MouseAdapter()
        {
            public void mouseReleased(MouseEvent Me)
            {
                if(Me.isPopupTrigger())
                {
                    Pmenu.show(Me.getComponent(), Me.getX(), Me.getY());
                }
            }
        });

        if(getClass().equals(Page.class))
        {
            newSectionMenuItem.setEnabled(false);
        }
    }


    /**
     * Returns all the nodes in this tree from doing a left heavy recursive
     * traversal of the tree from the given root
     * @param root The root from which to start the search
     * @return A list of the nodes
     */
    public ArrayList getAllNodesInOrder(BCStructure root)
    {
        ArrayList nodes = new ArrayList();
        getAllNodesInOrderRec(root, nodes);
        return nodes;
    }

    /**
     * Recursive function that gets the nodes in the tree
     * @param currNode
     * @param theNodes
     */
    private void getAllNodesInOrderRec(BCStructure currNode, ArrayList theNodes)
    {
        theNodes.add(currNode);
        for(int i = 0; i lt currNode.getChildCount(); i++)
        {
            currNode.getAllNodesInOrderRec((BCStructure) currNode.getChildAt(i), theNodes);
        }
    }


}


在上面的示例中,您看到的实际节点是名为Page的BCStructure的子类。这是我正在重命名的实际类。


package Structure;

import Components.BCFrame;
import Components.Basic.BackGroundImage;
import GUI.Window;
import Logging.LogRunner;
import XMLProcessing.XMLWriter;
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.tree.DefaultTreeCellRenderer;

/**
 * This class is responcible for holding the components the make up a page and
 * is accessible through the tree structure. In other words, this class is what
 * actually makes up a page. It holds the componenets in an array, and since it
 * node in a tree, it can be notified when it has been clicked, and load the
 * compoenents it is holding.
 * @author dvargo
 */
public class Page extends BCStructure
{
    /**
     * Holds all the componenets in the content pane so an action can be done on
     * all componenets. Also sets the added component to the current component.
     */
    private ArrayList theComponents = new ArrayList()
    {
        @Override
        public boolean add(BCFrame e)
        {
            e.setPage(selfReference);
            return super.add(e);
        }
    };


    /**
     * Self reference to this page
     */
    private Page selfReference = this;

    /**
     * The dimensions of this page. It defualts to a medium page size
     */
    private Dimension pageSize = Window.NORMAL;

    /**
     * This bages background;
     */
    private BackGroundImage background;

    /**
     * Constructor that sets the node up in the tree and inializes values.
     * @param newName - Name for this node
     * @param inWindow - Reference to the main window
     * @param inRoot - The section or module that is the root for this page.
     */
    public Page(String newName, Window inWindow)
    {
        super(newName, inWindow,false);
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
        ImageIcon theImage = new ImageIcon(new JFrame().getToolkit().getImage(getClass().getResource("/GUI/fileIcon.png")));
        renderer.setLeafIcon(theImage);
        //set the background color to white, there will always be a background
        background = new BackGroundImage(0,0,pageSize.width,pageSize.height,mainWindow);
        background.setColor(Color.WHITE);
        theComponents.add(background);
        //you must add this to the content pane to keep indexes correct. it will not display anything though
        mainWindow.getComponentContentPane().add(background,0);
        mainWindow.getContentPanePanel().repaint();
    }


    /**
     * Loads all the componenets held in the arraylist to to the screen.
     */
    public void loadPage()
    {
        //remove the background of the previous page
        mainWindow.getComponentContentPane().removeAll();
        mainWindow.setPageSizeComboSeleted(pageSize);
        background.setSize(pageSize);
        mainWindow.getComponentContentPane().setPreferredSize(pageSize);
        mainWindow.getComponentContentPane().setSize(pageSize);
        for(BCFrame currentComp : theComponents)
        {
            mainWindow.getComponentContentPane().add(currentComp);
            currentComp.setVisible(true);
            currentComp.revalidate();
            currentComp.repaint();
            currentComp.setPage(this);
       }

        mainWindow.getComponentContentPane().repaint();
        mainWindow.getComponentContentPane().revalidate();

    }

    /**
     * Writes the componenets to file in XML.
     * @param filePath - The path and name of the file to write.
     */
    public void save(String filePath)
    {
        XMLWriter theWriter = new XMLWriter();
        for(int i = 0; i  newComponents)
    {
        theComponents = newComponents;
        boolean backgroundExists = false;
        for(BCFrame curr : theComponents)
        {
            if(curr.getClass().equals(BackGroundImage.class))
            {
                background = (BackGroundImage) curr; //make sure background isnt null
                backgroundExists = true;
            }
            curr.setPage(this);
        }
        if(backgroundExists)
        {
            return;
        }
        LogRunner.getLogger().severe("Could not find a background while setting the components, adding a new dfualt white one");
        BackGroundImage bgi= new BackGroundImage();
        bgi.setSize(pageSize);
        bgi.setColor(Color.WHITE);
        theComponents.add(bgi);
        background = bgi;
    }

    public ArrayList getComponents()
    {
        return theComponents;
    }



}



2 个答案:

答案 0 :(得分:2)

我明白了。如果您注意到BCStructure,它有一个名为name的值。每当我更改节点的名称时,我都不会更新此值。然后,如果您注意到Page类的copy(),它将使用此名称变量。复制在拖放过程中使用。如果名称没有更新,它将使用旧值,这就是我看到我所做的行为的原因。有点简单,但难以解释。感谢你的帮助。

答案 1 :(得分:1)

我看不到你用来创建TreeModel的代码,但是我猜你没有使用 mutable 节点:

  

http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/tree/MutableTreeNode.html#setUserObject%28java.lang.Object%29