2017-12-24 41 views
0

docs.oracle.com 자습서의 DynamicTree 및 DynamicTreeDemo 클래스를 사용하고 있습니다. 주어진 예제는 선택된 노드에 자식 노드를 동적으로 추가 할 수 있습니다.수동 특정 행의 JTree에 노드 삽입

I가 변화하는 TreePath 대한

DefaultMutableTreeNode addObject(Object child) 

함수를 수정했다. 그것은 내가 추가 버튼을 클릭 할 때마다 그 경로에만 자식 노드를 추가 할 수 있도록 트리 경로를 수정했습니다.

Object[] o = { new DefaultMutableTreeNode("Root Node"), new DefaultMutableTreeNode("Parent 2"), 
      new DefaultMutableTreeNode("Child 2") }; 

    parentPath = new TreePath(o); 

하지만 내 수정 후 추가 버튼이 작동하지 않습니다. 어떻게 코드에서 경로를 변경하여 노드를 추가 할 수 있도록이 문제를 해결할 수 있습니까?

import java.awt.GridLayout; 
import java.awt.Toolkit; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeModel; 
import javax.swing.tree.MutableTreeNode; 
import javax.swing.tree.TreePath; 
import javax.swing.tree.TreeSelectionModel; 
import javax.swing.event.TreeModelEvent; 
import javax.swing.event.TreeModelListener; 

public class DynamicTree extends JPanel { 
protected DefaultMutableTreeNode rootNode; 
protected DefaultTreeModel treeModel; 
protected JTree tree; 
private Toolkit toolkit = Toolkit.getDefaultToolkit(); 

public DynamicTree() { 
    super(new GridLayout(1, 0)); 

    rootNode = new DefaultMutableTreeNode("Root Node"); 
    treeModel = new DefaultTreeModel(rootNode); 
    treeModel.addTreeModelListener(new MyTreeModelListener()); 
    tree = new JTree(treeModel); 
    tree.setEditable(true); 
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 
    tree.setShowsRootHandles(true); 

    JScrollPane scrollPane = new JScrollPane(tree); 
    add(scrollPane); 
} 

/** Remove all nodes except the root node. */ 
public void clear() { 
    rootNode.removeAllChildren(); 
    treeModel.reload(); 
} 

/** Remove the currently selected node. */ 
public void removeCurrentNode() { 
    TreePath currentSelection = tree.getSelectionPath(); 
    if (currentSelection != null) { 
     DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent()); 
     MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent()); 
     if (parent != null) { 
      treeModel.removeNodeFromParent(currentNode); 
      return; 
     } 
    } 

    // Either there was no selection, or the root was selected. 
    toolkit.beep(); 
} 

/** Add child to the currently selected node. */ 
public DefaultMutableTreeNode addObject(Object child) { 
    DefaultMutableTreeNode parentNode = null; 
    TreePath parentPath = tree.getSelectionPath(); 

    //////////////////////////// Modification for fixing place /////////////  

    Object[] o = { new DefaultMutableTreeNode("Root Node"), new DefaultMutableTreeNode("Parent 2"), 
      new DefaultMutableTreeNode("Child 2") }; 

    parentPath = new TreePath(o); 

    //////////////////////////// end of modification/////////////////////// 


    if (parentPath == null) { 
     parentNode = rootNode; 
    } else { 
     parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); 
    } 

    return addObject(parentNode, child, true); 
} 

public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child) { 
    return addObject(parent, child, false); 
} 

public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child, boolean shouldBeVisible) { 
    DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child); 

    if (parent == null) { 
     parent = rootNode; 
    } 

    // It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode 
    treeModel.insertNodeInto(childNode, parent, parent.getChildCount()); 

    // Make sure the user can see the lovely new node. 
    if (shouldBeVisible) { 
     tree.scrollPathToVisible(new TreePath(childNode.getPath())); 
    } 
    return childNode; 
} 

class MyTreeModelListener implements TreeModelListener { 
    public void treeNodesChanged(TreeModelEvent e) { 
     DefaultMutableTreeNode node; 
     node = (DefaultMutableTreeNode) (e.getTreePath().getLastPathComponent()); 

     /* 
     * If the event lists children, then the changed node is the child of the node 
     * we've already gotten. Otherwise, the changed node and the specified node are 
     * the same. 
     */ 

     int index = e.getChildIndices()[0]; 
     node = (DefaultMutableTreeNode) (node.getChildAt(index)); 

     System.out.println("The user has finished editing the node."); 
     System.out.println("New value: " + node.getUserObject()); 
    } 

    public void treeNodesInserted(TreeModelEvent e) { 
    } 

    public void treeNodesRemoved(TreeModelEvent e) { 
    } 

    public void treeStructureChanged(TreeModelEvent e) { 
    } 
} 
} 





import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.tree.DefaultMutableTreeNode; 

public class DynamicTreeDemo extends JPanel implements ActionListener { 
private int newNodeSuffix = 1; 
private static String ADD_COMMAND = "add"; 
private static String REMOVE_COMMAND = "remove"; 
private static String CLEAR_COMMAND = "clear"; 

private DynamicTree treePanel; 

public DynamicTreeDemo() { 
    super(new BorderLayout()); 

    // Create the components. 
    treePanel = new DynamicTree(); 
    populateTree(treePanel); 

    JButton addButton = new JButton("Add"); 
    addButton.setActionCommand(ADD_COMMAND); 
    addButton.addActionListener(this); 

    JButton removeButton = new JButton("Remove"); 
    removeButton.setActionCommand(REMOVE_COMMAND); 
    removeButton.addActionListener(this); 

    JButton clearButton = new JButton("Clear"); 
    clearButton.setActionCommand(CLEAR_COMMAND); 
    clearButton.addActionListener(this); 

    // Lay everything out. 
    treePanel.setPreferredSize(new Dimension(300, 150)); 
    add(treePanel, BorderLayout.CENTER); 

    JPanel panel = new JPanel(new GridLayout(0, 3)); 
    panel.add(addButton); 
    panel.add(removeButton); 
    panel.add(clearButton); 
    add(panel, BorderLayout.SOUTH); 
} 

public void populateTree(DynamicTree treePanel) { 
    String p1Name = new String("Parent 1"); 
    String p2Name = new String("Parent 2"); 
    String c1Name = new String("Child 1"); 
    String c2Name = new String("Child 2"); 

    DefaultMutableTreeNode p1, p2; 

    p1 = treePanel.addObject(null, p1Name); 
    p2 = treePanel.addObject(null, p2Name); 

    treePanel.addObject(p1, c1Name); 
    treePanel.addObject(p1, c2Name); 

    treePanel.addObject(p2, c1Name); 
    treePanel.addObject(p2, c2Name); 
} 

public void actionPerformed(ActionEvent e) { 
    String command = e.getActionCommand(); 

    if (ADD_COMMAND.equals(command)) { 
     // Add button clicked 
     treePanel.addObject("New Node " + newNodeSuffix++); 
    } else if (REMOVE_COMMAND.equals(command)) { 
     // Remove button clicked 
     treePanel.removeCurrentNode(); 
    } else if (CLEAR_COMMAND.equals(command)) { 
     // Clear button clicked. 
     treePanel.clear(); 
    } 
} 

/** 
* Create the GUI and show it. For thread safety, this method should be invoked 
* from the event-dispatching thread. 
*/ 
private static void createAndShowGUI() { 
    // Create and set up the window. 
    JFrame frame = new JFrame("DynamicTreeDemo"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    // Create and set up the content pane. 
    DynamicTreeDemo newContentPane = new DynamicTreeDemo(); 
    newContentPane.setOpaque(true); // content panes must be opaque 
    frame.setContentPane(newContentPane); 

    // Display the window. 
    frame.pack(); 
    frame.setVisible(true); 
} 

public static void main(String[] args) { 
    // Schedule a job for the event-dispatching thread: 
    // creating and showing this application's GUI. 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGUI(); 
     } 
    }); 
} 
} 

답변

0

당신이 만든 변경으로 인해 기존의 새로운 TreePath이 같은 TreePath 객체되지 않을 것 노드와 동일한 이름으로 새로운 DefaultMutableTreeNode의를 작성하여 올바르지 않습니다. 그들의 참고 문헌은 동일하지 않습니다. 그러면 생성중인이 새로운 경로는 TreeModel에서 찾을 수 없으므로 결과는 아무런 변화가 없습니다.

TreeModel 자체에서 새 노드를 삽입 할 경로를 가져야합니다. 특정 위치에 새 노드를 추가하려면

// ////////////////////////// Modification for fixing place // ///////////// 

Object[] o = { rootNode.getLastLeaf() }; // For you testing purposes 
             // this will return the Child 2" reference, 
             // next time it will return "New Node 2" and so on. 

parentPath = new TreePath(o); 

// ////////////////////////// end of modification/////////////////////// 

, 당신에 대한 참조를 얻어야한다 : 예를 들어, 당신은 2이 같은 그것의 참조를 얻을 수있는 아동에 새로운 아이를 추가하려면 TreeModel의 기존 노드 TreeNode은 현재 TreeModel에 존재하지 않습니다.

희망이 도움이됩니다.

+0

답변 해 주셔서 감사합니다. 나는이 방법을 이전에 시도했고 효과가있다. 하지만 난 내 코드에서 작성됩니다 특정 경로에 노드를 삽입하고 싶습니다. 예를 들어, 위 코드에서 "Root Node/Paren 2/Child 2"라고 썼습니다. 이 경로는 클릭마다 달라집니다. 나는 tree.getSelectionPath()를 사용하는 대신에 treepath를 바꾸기 위해 여기에 붙어있다. 내가 어떻게 할 수 있는지 모르겠다. –

+0

트리에 새 노드를 추가하는 방법을 모르겠지만 메모리에서 새 TreeNode 참조를 만들지 않고 TreeModel 자체에서 해당 경로를 찾는 것이 중요합니다. 같은 이름을 가진'new DefaultMutableTreeNode'를 생성하기 전에 내가 말했듯이 기존 노드에 대한 참조를 treeModel로 만들지 않습니다. 트리에 새로운 노드를 추가하는 커스텀 로직을 가지고 있다면,'rootNode' 또는'selectedNode'에서 시작하여 treeModel을 탐색하여 특정 노드를 새로운 노드의 부모 노드로 찾아야합니다. – STaefi