1. 트리 컴포넌트
▷ 계층적인 데이터를 표시하는 컴포넌트, Swing은 트리 컴포넌트로 JTree를 제공
▷ 하나의 루트 노드 아래에 여러 개의 자식 노드를 가지며, 자식 노드는 또 다시 자식 노드를 가질 수 있음
▷ 동일한 부모 노드를 갖는 노드들을 묶어서 형제 노드라고 부르며, 자식 노드가 없는 마지막 노드는 잎사귀 노드(리프 노드)라고 함
(1) 트리 생성
▷ 생성자의 매개값으로 루트 노드를 대입해야 하는데, 루트 노드는 DefaultMutableTreeNode로 생성
▷ 부모 노드, 리프 노드를 생성하는데도 사용
◎ 기본적인 노드 모양 나타내는 예제
import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultMutableTreeNode; public class JTreeExample extends JFrame { private JTree jTree; public JTreeExample() { this.setTitle("JTreeExample"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().add(new JScrollPane(getJTree()), BorderLayout.CENTER); this.setSize(200, 150); } // JTree 생성 public JTree getJTree() { if(jTree == null) { DefaultMutableTreeNode root = new DefaultMutableTreeNode("그룹리스트"); DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("친구"); node1.add(new DefaultMutableTreeNode("친구1")); node1.add(new DefaultMutableTreeNode("친구2")); root.add(node1); DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("회사동료"); node2.add(new DefaultMutableTreeNode("동료1")); node2.add(new DefaultMutableTreeNode("동료2")); root.add(node2); jTree = new JTree(root); } return jTree; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JTreeExample jFram = new JTreeExample(); jFram.setVisible(true); } }); } }
메신저와 유사한 형태로 만들 수 있습니다.
(2) 노드 표현 변경
▷ TreeCellRenderer를 만들어 기본 렌더러인 DefaultTreeCellRenderer를 대체해 노드 아이콘과 리프 노드 표현 변형
◎ getTreeCellRendererComponent() 메소드 매개변수
NO | 매개변수 | 값 또는 참조 |
1 | tree | 노드를 포함하고 있는 JTree 참조 |
2 | value | 노드인 DefaultMutableTreeNode 객체 |
3 | sel | 노드가 선택되었는지 여부 |
4 | expanded | 부모 노드가 펼쳐졌는지 여부 |
5 | leaf | 리프 노드인지 여부 |
6 | hasFocus | 포커스를 가지고 있는지 여부 |
◎ 부모 노드의 아이콘 변경 및 리프 노드를 아이콘 + 글자+아이콘으로 표현하는 예제
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeCellRenderer; public class JTreeExample2 extends JFrame { private JTree jTree; public JTreeExample2() { this.setTitle("JTreeExample2"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().add(new JScrollPane(getJTree()), BorderLayout.CENTER); this.setSize(200, 150); } // JTree 생성 public JTree getJTree() { if(jTree == null) { DefaultMutableTreeNode root = new DefaultMutableTreeNode("그룹리스트"); DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("친구"); node1.add(new DefaultMutableTreeNode("친구1")); node1.add(new DefaultMutableTreeNode("친구2")); root.add(node1); DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("회사동료"); node2.add(new DefaultMutableTreeNode("동료1")); node2.add(new DefaultMutableTreeNode("동료2")); root.add(node2); jTree = new JTree(root); // 노드 표현 방법 변경 jTree.setCellRenderer(new MyTreeCellRenderer()); } return jTree; } // TreeCellRender 정의 public class MyTreeCellRenderer implements TreeCellRenderer{ public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { if(!leaf) { JLabel jLabel = new JLabel(); jLabel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); jLabel.setIcon(new ImageIcon(getClass().getResource("parentnode.gif"))); jLabel.setText(value.toString()); return jLabel; } else { JPanel jPanel = new JPanel(); jPanel.setBackground(Color.WHITE); jPanel.setLayout(new BorderLayout()); jPanel.setBorder(BorderFactory.createEmptyBorder(3,0,3,0)); // 노드 간 상하 간격 JLabel lblWest = new JLabel(new ImageIcon(getClass(). getResource("logon.gif"))); JLabel lblCenter = new JLabel(" " + value.toString()+" "); JLabel lblEast = new JLabel(new ImageIcon(getClass(). getResource("time.gif"))); jPanel.add(lblWest, BorderLayout.WEST); jPanel.add(lblCenter, BorderLayout.CENTER); jPanel.add(lblEast, BorderLayout.EAST); if(sel) { // 노드 선택시 오렌지 배경색 설정 jPanel.setBackground(Color.ORANGE); } return jPanel; } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JTreeExample2 jFram = new JTreeExample2(); jFram.setVisible(true); } }); } }
(3) 이벤트 처리
▷ 노드 선택이 변경되면 TreeSelectionEvent가 발생하기 때문에 TreeSelectionListener 를 추가해서 이벤트를 처리함
▷ TreeSelectionListener의 valueChanged() 메소드는 노드 선택이 변경되면 호출됨
◎ 노드 선택 및 더블클릭시 텍스트 이벤트 표시 예시
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseListener; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreePath; public class JTreeExample3 extends JFrame { private JTree jTree; public JTreeExample3() { this.setTitle("JTreeExample3"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().add(new JScrollPane(getJTree()), BorderLayout.CENTER); this.setSize(200, 150); } // JTree 생성 public JTree getJTree() { if(jTree == null) { DefaultMutableTreeNode root = new DefaultMutableTreeNode("그룹리스트"); DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("친구"); node1.add(new DefaultMutableTreeNode("친구1")); node1.add(new DefaultMutableTreeNode("친구2")); root.add(node1); jTree = new JTree(root); jTree.setCellRenderer(new MyTreeCellRenderer()); jTree.addTreeSelectionListener(treeSelectionListener); jTree.addMouseListener(mouseListener); DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("회사동료"); node2.add(new DefaultMutableTreeNode("동료1")); node2.add(new DefaultMutableTreeNode("동료2")); root.add(node2); } return jTree; } // TreeSelectionListener 필드 선언 private TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { // 사용자가 선택한 경로의 전체 경로 TreePath treePath = e.getPath(); DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treePath.getLastPathComponent(); // 사용자가 선택한 경로의 Value 값 반환 String nodeText = (String) treeNode.getUserObject(); JOptionPane.showMessageDialog(JTreeExample3.this, "노드 변경: " + nodeText); } }; // MouseListener 필드 선언 private MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent e) { // 더블 클릭이 되었을 경우에만 실행 if(e.getClickCount() == 2) { TreePath treePath = jTree.getPathForLocation(e.getX(), e.getY()); DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treePath.getLastPathComponent(); String nodeText = (String) treeNode.getUserObject(); JOptionPane.showMessageDialog(JTreeExample3.this, "더블 클릭: " + nodeText); } }; }; // TreeCellRender 정의 public class MyTreeCellRenderer implements TreeCellRenderer{ public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { if(!leaf) { JLabel jLabel = new JLabel(); jLabel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); jLabel.setIcon(new ImageIcon(getClass().getResource("parentnode.gif"))); jLabel.setText(value.toString()); return jLabel; } else { JPanel jPanel = new JPanel(); jPanel.setBackground(Color.WHITE); jPanel.setLayout(new BorderLayout()); jPanel.setBorder(BorderFactory.createEmptyBorder(3,0,3,0)); // 노드 간 상하 간격 JLabel lblWest = new JLabel(new ImageIcon(getClass(). getResource("logon.gif"))); JLabel lblCenter = new JLabel(" " + value.toString()+" "); JLabel lblEast = new JLabel(new ImageIcon(getClass(). getResource("time.gif"))); jPanel.add(lblWest, BorderLayout.WEST); jPanel.add(lblCenter, BorderLayout.CENTER); jPanel.add(lblEast, BorderLayout.EAST); if(sel) { // 노드 선택시 오렌지 배경색 설정 jPanel.setBackground(Color.ORANGE); } return jPanel; } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JTreeExample3 jFram = new JTreeExample3(); jFram.setVisible(true); } }); } }
JTree을 이용해 그룹을 만들어 펼치거나 접게 만들었습니다.
JTree를 이용하니 회사 사내 메신저나 옛날에 사용했던 네이트온 같은 모습이 나타나네요!!
더 많은 기능들에 대해서 배워볼게요~!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~
'BackEnd > Java' 카테고리의 다른 글
[java]이것이 자바다 부록 Java UI 11 (Swing을 이용한 툴바 컴포넌트) (0) | 2023.02.20 |
---|---|
[java]이것이 자바다 부록 Java UI 10 (Swing을 이용한 메뉴 컴포넌트) (0) | 2023.02.20 |
[java]이것이 자바다 부록 Java UI 8-1 (Swing을 이용한 테이블 컴포넌트 2) (0) | 2023.02.18 |
[java]이것이 자바다 부록 Java UI 8 (Swing을 이용한 테이블 컴포넌트 1) (0) | 2023.02.18 |
[java]이것이 자바다 부록 Java UI 6-1 (Swing을 이용한 텍스트 컴포넌트 2) (0) | 2023.02.17 |