2014-07-07 8 views
0

내가 스윙 예에서 표준의 JTree를 수정하려면 확장과 같은 구조를 가진 두 나무 축소 - 응용 프로그램의>Dynamic Tree Example 스크린 샷은 다음과 같습니다 : DynamicTreeDemo이 링크에 주어진 동시에

enter image description here

두 나무를 유지하기 위해이 구조를 사용하고 싶습니다. 둘 다 똑같은 구조를 유지하고 있습니다. 둘 중 하나를 마우스로 클릭하여 축소/확장하면 축소 및 확장 할 수 있어야합니다.
또한 두 트리 중 하나에서 노드를 선택하면 다른 트리의 해당 노드도 강조 표시됩니다.
하나의 트리에 파일/폴더가 노드로 포함되어 있고 다른 트리에는 노드로 생성 시간이있을 수 있습니다.

각 DynamicTree 객체에서 하나의 Jtree 객체 만 사용하여이 작업을 수행 할 수 있습니까? Jtree가 각 트리의 해당 노드에서 데이터를 포함하는 하나의 객체 만 저장하고 이러한 데이터를 별도의 트리에 표시하도록 할 수있는 방법이 있습니까?

현재 두 개의 Jtree를 사용 중이며 두 명의 부모와 두 명의 어린이를 추가 함수에 대한 입력으로 가져와 해당하는 자식을 해당 부모에 추가하여 노드를 추가 할 수 있습니다.
그러나 제거/확장/축소 기능에서 두 트리에서 두 노드를 제거/확장/축소해야합니다. 어떻게해야합니까?

저는 자바 스윙에 익숙하지만 자바 프로그래밍에는 익숙하지 않습니다. 그러니 Jswing에 대한 지식이 필요한 부분을 명료하게 설명하십시오.

미리 감사드립니다.

+0

두 트리 모두에 하나의'TreeModel'을 사용할 수 있어야합니다. 각 노드가 다르게 노드 데이터를 렌더링하도록해야합니다 ... – MadProgrammer

+0

스윙을 처음 사용하기 때문에 예제로 설명해 주실 수 있습니까? JTree 또는 JTree가 아직 하나 있습니까? – TSG

+0

그러면 가장 먼저 살펴볼 사항은 [나무 사용 방법]입니다 (http://docs.oracle.com/).com/javase/tutorial/uiswing/components/tree.html) – MadProgrammer

답변

2

그래서, 트릭 트리의 SelectionModel들과 두 개의 사용자 정의 TreeCellRenderer의 링크를 결정하는 트리/확장 붕괴하고 그 결과를 반영하는 TreeExpansionListener 수를 사용하여, 하나의 TreeModel을 사용하는 것입니다.

기본적으로 각 트리는 TreeModelSelectionModel을 공유하므로 두 모델의 변경 내용에 모두 응답하므로 작업이 훨씬 간단 해집니다.

확장/축소는 사용자 정의 TreeExpansionListener을 통해 처리해야하기 때문에 조금 어렵습니다. 누가 이벤트를 트리거했는지 감지 한 다음 변경 사항을 반대 트리에 알립니다. 이 트리의에 의해 표시되어야 데이터에 대한 기본 정보를 포함하여

다음, 나는

마지막으로

, 나는의 다양한 측면을 렌더링하기 위해 두 개의 서로 다른 TreeCellRenderer의를 사용하여 ... 공통의 "데이터 객체"를 사용 TreeModel

Tree

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 
import javax.swing.event.TreeExpansionEvent; 
import javax.swing.event.TreeExpansionListener; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeCellRenderer; 
import javax.swing.tree.DefaultTreeModel; 
import javax.swing.tree.MutableTreeNode; 
import javax.swing.tree.TreePath; 

public class DynamicTreeDemo extends JPanel implements ActionListener { 

    protected static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss"); 

    private int newNodeSuffix = 1; 
    private static String ADD_COMMAND = "add"; 
    private static String REMOVE_COMMAND = "remove"; 
    private static String CLEAR_COMMAND = "clear"; 

    private DefaultMutableTreeNode rootNode; 
    private final DefaultTreeModel treeModel; 

    private JTree left; 
    private JTree right; 

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

     rootNode = new DefaultMutableTreeNode("Root Node"); 
     treeModel = new DefaultTreeModel(rootNode); 

     left = new JTree(treeModel); 
     left.setCellRenderer(new LeftTreeCellRenderer()); 
     right = new JTree(treeModel); 
     right.setCellRenderer(new RightTreeCellRenderer()); 

     MyExpansionListener expansionListener = new MyExpansionListener(left, right); 

     left.addTreeExpansionListener(expansionListener); 
     right.addTreeExpansionListener(expansionListener); 

     right.setSelectionModel(left.getSelectionModel()); 

     populateModel(); 

     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); 

     JPanel panel = new JPanel(new GridLayout(1, 2)); 
     panel.add(new JScrollPane(left)); 
     panel.add(new JScrollPane(right)); 
     add(panel, BorderLayout.CENTER); 

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

    protected TreeData createNodeData() { 
     return new TreeData("New Node " + newNodeSuffix++, SDF.format(new Date())); 
    } 

    public void populateModel() { 
     String p1Name = "Parent 1"; 
     String p2Name = "Parent 2"; 

     DefaultMutableTreeNode p1, p2; 

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

     addObject(p1, createNodeData()); 
     addObject(p1, createNodeData()); 

     addObject(p2, createNodeData()); 
     addObject(p2, createNodeData()); 

    } 

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

     if (ADD_COMMAND.equals(command)) { 
      // Add button clicked 
      addObject(createNodeData()); 
     } else if (REMOVE_COMMAND.equals(command)) { 
      // Remove button clicked 
      removeCurrentNode(); 
     } else if (CLEAR_COMMAND.equals(command)) { 
      // Clear button clicked. 
      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(); 
      } 
     }); 
    } 

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

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

     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) { 
      left.scrollPathToVisible(new TreePath(childNode.getPath())); 
      right.scrollPathToVisible(new TreePath(childNode.getPath())); 
     } 
     return childNode; 
    } 

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

    } 

    public class TreeData { 

     private String left; 
     private String right; 

     public TreeData(String left, String right) { 
      this.left = left; 
      this.right = right; 
     } 

     public String getLeft() { 
      return left; 
     } 

     public String getRight() { 
      return right; 
     } 

    } 

    public class LeftTreeCellRenderer extends DefaultTreeCellRenderer { 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
      if (value instanceof DefaultMutableTreeNode) { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; 
       Object userData = node.getUserObject(); 
       if (userData instanceof TreeData) { 
        value = ((TreeData) userData).getLeft(); 
       } 
      } 
      return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 
     } 

    } 

    public class RightTreeCellRenderer extends DefaultTreeCellRenderer { 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
      if (value instanceof DefaultMutableTreeNode) { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; 
       Object userData = node.getUserObject(); 
       if (userData instanceof TreeData) { 
        value = ((TreeData) userData).getRight(); 
       } 
      } 
      return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 
     } 

    } 

    public class MyExpansionListener implements TreeExpansionListener { 

     private JTree left; 
     private JTree right; 

     public MyExpansionListener(JTree left, JTree right) { 
      this.left = left; 
      this.right = right; 
     } 

     @Override 
     public void treeExpanded(TreeExpansionEvent event) { 
      TreePath path = event.getPath(); 
      if (event.getSource() == left) { 
       right.expandPath(path); 
      } else { 
       left.expandPath(path); 
      } 
     } 

     @Override 
     public void treeCollapsed(TreeExpansionEvent event) { 
      TreePath path = event.getPath(); 
      if (event.getSource() == left) { 
       right.collapsePath(path); 
      } else { 
       left.collapsePath(path); 
      } 
     } 

    } 
} 

에 의해 유지되는 데이터는 자세한 내용은 How to Use Trees를 참조

+0

감사합니다. 정확히 내가 필요로하는 것. 불행히도, 나는 충분한 평판이 없기 때문에 대답을 포기할 수 없습니다. 편집 : 아직 수정해야 할 2 JScrollPanes 사이의 동기화 문제가 있습니다. 그렇지 않으면 완벽 해. – TSG