2013-10-17 2 views
2

저는 JTreeJTextField입니다. 트리에서 노드를 선택하면 텍스트 필드에 노드 값이 표시됩니다. 그런 다음 텍스트를 편집하고 저장하여 선택한 노드의 값을 변경할 수 있습니다. 나는 DefaultTreeModelnodeChanged 메서드를 사용하여 트리를 업데이트합니다.'nodeChanged'를 사용하여 트리 노드를 업데이트하는 것이 맞습니까

트리 모델에 노드 업데이트를 알리는 적절한 방법입니까? 내게는 명백하게 나무의 모델에 액세스하여 무언가가 일어 났음을 말하기 때문에 추한 것처럼 보입니다.

여기 DefaultTreeModel을하고 DefaultMutableTreeNode에 대한 JavaDoc을 코드 주위에 파고에서 일부 코드

import java.awt.BorderLayout; 
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.JScrollPane; 
import javax.swing.JTextField; 
import javax.swing.JTree; 
import javax.swing.ScrollPaneConstants; 
import javax.swing.event.TreeSelectionListener; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeModel; 

public class TextPaneTest extends JFrame { 

    private JTextField textBox = null; 
    private JTree tree = null; 
    private JButton button = null; 

    public static void main(String args[]) { 
     new TextPaneTest(); 
    } 

    public TextPaneTest() { 

     // Main panel 
     JPanel panel = new JPanel(); 
     panel.setLayout(new BorderLayout()); 

     // Panel holding tree 
     JPanel treePanel = new JPanel(); 
     treePanel.setLayout(new BorderLayout()); 

     // Panel holding text field and button 

     JPanel editPanel = new JPanel(); 
     editPanel.setLayout(new BorderLayout()); 

     // My textbox 
     textBox = new JTextField(); 

     // button 
     button = new JButton(); 
     button.setText("Save changes"); 
     button.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) 
      { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 
       String text = textBox.getText(); 
       node.setUserObject(text); 
       DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); 
       model.nodeChanged(node); 
      } 
     }); 

     // My Tree 
     DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root"); 
     tree = new JTree(top); 
     tree.addTreeSelectionListener(new TreeSelectionListener() { 
      public void valueChanged(javax.swing.event.TreeSelectionEvent evt) { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 
       textBox.setText(node.getUserObject().toString()); 
     } 
     }); 

     JScrollPane scrollPane = new JScrollPane(tree); 
     scrollPane.setHorizontalScrollBarPolicy(
      ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

     // Add tree 
     treePanel.add(scrollPane); 
     panel.add(treePanel, BorderLayout.CENTER); 

     // Add box and button to edit panel 
     editPanel.add(textBox, BorderLayout.CENTER); 
     editPanel.add(button, BorderLayout.SOUTH); 

     // Add edit panel 
     panel.add(editPanel, BorderLayout.SOUTH); 

     // Add everything to the frame 
     this.add(panel); 
     this.setSize(300, 200); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 
    } 
} 

답변

1

, 난 당신이하고있는 것은 괜찮습니다 생각합니다. 모델의 구조를 변경 한 경우 (예 : 노드를 제거한 경우) 모델에서 아무 것도 호출하지 않아도됩니다. TreeModel은 사용자가 무언가를했는지 알 수 있기 때문입니다. 그러나이 경우 모델이 참조하는 노드의 내용을 변경하려고합니다. 따라서 노드 중 하나의 내용이 이제는 다르다는 것을 TreeModel에 알려야 할 것이 합리적입니다.

나 자신을 놓친 것일 수도 있지만 괜찮은 사람이라고 생각합니다.

2

예제가 올바르게 표시됩니다. @ matt의 정확한 answer을 확장하면이 MVC illustration에서 통찰력을 얻을 수 있습니다. JTree보기도 편집을 허용하기 때문에 모델의 메소드를 호출 할 수 있습니다. 모델은 차례로 fireTreeNodesChanged()을 호출하여 트리 자체를 포함하여 모든 수신기를 알립니다.

  • 스윙 GUI 개체를 구성하고 event dispatch thread을 조작해야합니다

    tree.getModel().addTreeModelListener(new TreeModelListener() { 
        @Override 
        public void treeNodesChanged(TreeModelEvent e) { 
         update(e); 
        } 
    
        @Override 
        public void treeNodesInserted(TreeModelEvent e) { 
         update(e); 
        } 
    
        @Override 
        public void treeNodesRemoved(TreeModelEvent e) { 
         update(e); 
        } 
    
        @Override 
        public void treeStructureChanged(TreeModelEvent e) { 
         update(e); 
        } 
    
        private void update(TreeModelEvent e) { 
         System.out.println(e); 
        } 
    }); 
    

    추가 참고 : 효과를 보려면, 다른 청취자를 추가합니다.

  • 대신 setSize()을 사용하는 대신 트리 패널의 getPreferredSize() 메서드와 둘러싸는 프레임 pack()을 재정의하십시오. 그냥 완전성에 대한

    JPanel treePanel = new JPanel(){ 
    
        @Override 
        public Dimension getPreferredSize() { 
         return new Dimension(300, 200); 
        } 
    }; 
    … 
    this.pack(); 
    
4

: 당신은`nodeChanged()가`didn를 일을 어떤 이유로, 모델 API를

TreePath selected = tree.getSelectionPath(); 
tree.getModel().valueForPathChanged(selected, textBox.getText()); 
+0

를 통해 독점적으로 노드를 업데이트 한 경우가 약간 덜 추한을 보일 수 있습니다 't (특정'TreeCellRenderer'를 가지고 있는데 차이가 나는지 모르겠다.). 어쨌든, +1! :) – Matthieu

관련 문제