Java tutorial
import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.swing.tree.*; public class AncestorTree extends JFrame { public static ImageIcon ICON_SELF = new ImageIcon("myself.gif"); public static ImageIcon ICON_MALE = new ImageIcon("male.gif"); public static ImageIcon ICON_FEMALE = new ImageIcon("female.gif"); protected JTree m_tree; protected DefaultTreeModel m_model; protected IconCellRenderer m_renderer; protected IconCellEditor m_editor; public AncestorTree() { super("Ancestor Tree"); setSize(400, 300); DefaultMutableTreeNode top = new DefaultMutableTreeNode(new IconData(ICON_SELF, "Myself")); addAncestors(top); m_model = new DefaultTreeModel(top); m_tree = new JTree(m_model); m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); m_tree.setShowsRootHandles(true); m_tree.setEditable(true); m_renderer = new IconCellRenderer(); m_tree.setCellRenderer(m_renderer); m_editor = new IconCellEditor(m_tree); m_tree.setCellEditor(m_editor); m_tree.setInvokesStopCellEditing(true); m_tree.addMouseListener(new TreeExpander()); JScrollPane s = new JScrollPane(); s.getViewport().add(m_tree); getContentPane().add(s, BorderLayout.CENTER); WindowListener wndCloser = new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }; addWindowListener(wndCloser); setVisible(true); } public boolean addAncestors(DefaultMutableTreeNode node) { if (node.getChildCount() > 0) return false; Object obj = node.getUserObject(); if (obj == null) return false; node.add(new DefaultMutableTreeNode(new IconData(ICON_MALE, "Father of: " + obj.toString()))); node.add(new DefaultMutableTreeNode(new IconData(ICON_FEMALE, "Mother of: " + obj.toString()))); return true; } public static void main(String argv[]) { new AncestorTree(); } class TreeExpander extends MouseAdapter { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { TreePath selPath = m_tree.getPathForLocation(e.getX(), e.getY()); if (selPath == null) return; DefaultMutableTreeNode node = (DefaultMutableTreeNode) (selPath.getLastPathComponent()); if (node != null && addAncestors(node)) { m_tree.expandPath(selPath); m_tree.repaint(); } } } } } class IconCellRenderer extends JLabel implements TreeCellRenderer { protected Color m_textSelectionColor; protected Color m_textNonSelectionColor; protected Color m_bkSelectionColor; protected Color m_bkNonSelectionColor; protected Color m_borderSelectionColor; protected boolean m_selected; public IconCellRenderer() { super(); m_textSelectionColor = UIManager.getColor("Tree.selectionForeground"); m_textNonSelectionColor = UIManager.getColor("Tree.textForeground"); m_bkSelectionColor = UIManager.getColor("Tree.selectionBackground"); m_bkNonSelectionColor = UIManager.getColor("Tree.textBackground"); m_borderSelectionColor = UIManager.getColor("Tree.selectionBorderColor"); setOpaque(false); } public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; Object obj = node.getUserObject(); setText(obj.toString()); if (obj instanceof IconData) { IconData idata = (IconData) obj; if (expanded) setIcon(idata.getOpenIcon()); else setIcon(idata.getIcon()); } else setIcon(null); setFont(tree.getFont()); setForeground(sel ? m_textSelectionColor : m_textNonSelectionColor); setBackground(sel ? m_bkSelectionColor : m_bkNonSelectionColor); m_selected = sel; return this; } public void paint(Graphics g) { Color bColor = getBackground(); Icon icon = getIcon(); g.setColor(bColor); int offset = 0; if (icon != null && getText() != null) offset = (icon.getIconWidth() + getIconTextGap()); g.fillRect(offset, 0, getWidth() - 1 - offset, getHeight() - 1); if (m_selected) { g.setColor(m_borderSelectionColor); g.drawRect(offset, 0, getWidth() - 1 - offset, getHeight() - 1); } super.paint(g); } } class IconData { protected Icon m_icon; protected Icon m_openIcon; protected Object m_data; public IconData(Icon icon, Object data) { m_icon = icon; m_openIcon = null; m_data = data; } public IconData(Icon icon, Icon openIcon, Object data) { m_icon = icon; m_openIcon = openIcon; m_data = data; } public Icon getIcon() { return m_icon; } public Icon getOpenIcon() { return m_openIcon != null ? m_openIcon : m_icon; } public Object getObject() { return m_data; } public String toString() { return m_data.toString(); } } class IconCellEditor extends JLabel implements TreeCellEditor, ActionListener { protected JTree m_tree = null; protected JTextField m_editor = null; protected IconData m_item = null; protected int m_lastRow = -1; protected long m_lastClick = 0; protected Vector m_listeners = null; public IconCellEditor(JTree tree) { super(); m_tree = tree; m_listeners = new Vector(); } public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { if (value instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; Object obj = node.getUserObject(); if (obj instanceof IconData) { IconData idata = (IconData) obj; m_item = idata; // Reserve some more space... setText(idata.toString() + " "); setIcon(idata.m_icon); setFont(tree.getFont()); return this; } } // We don't support other objects... return null; } public Object getCellEditorValue() { if (m_item != null && m_editor != null) m_item.m_data = m_editor.getText(); return m_item; } public boolean isCellEditable(EventObject evt) { if (evt instanceof MouseEvent) { MouseEvent mEvt = (MouseEvent) evt; if (mEvt.getClickCount() == 1) { int row = m_tree.getRowForLocation(mEvt.getX(), mEvt.getY()); if (row != m_lastRow) { m_lastRow = row; m_lastClick = System.currentTimeMillis(); return false; } else if (System.currentTimeMillis() - m_lastClick > 1000) { m_lastRow = -1; m_lastClick = 0; prepareEditor(); mEvt.consume(); return true; } else return false; } } return false; } protected void prepareEditor() { if (m_item == null) return; String str = m_item.toString(); m_editor = new JTextField(str); m_editor.addActionListener(this); m_editor.selectAll(); m_editor.setFont(m_tree.getFont()); add(m_editor); revalidate(); TreePath path = m_tree.getPathForRow(m_lastRow); m_tree.startEditingAtPath(path); } protected void removeEditor() { if (m_editor != null) { remove(m_editor); m_editor.setVisible(false); m_editor = null; m_item = null; } } public void doLayout() { super.doLayout(); if (m_editor != null) { int offset = getIconTextGap(); if (getIcon() != null) offset += getIcon().getIconWidth(); Dimension cSize = getSize(); m_editor.setBounds(offset, 0, cSize.width - offset, cSize.height); } } public boolean shouldSelectCell(EventObject evt) { return true; } public boolean stopCellEditing() { if (m_item != null) m_item.m_data = m_editor.getText(); ChangeEvent e = new ChangeEvent(this); for (int k = 0; k < m_listeners.size(); k++) { CellEditorListener l = (CellEditorListener) m_listeners.elementAt(k); l.editingStopped(e); } removeEditor(); return true; } public void cancelCellEditing() { ChangeEvent e = new ChangeEvent(this); for (int k = 0; k < m_listeners.size(); k++) { CellEditorListener l = (CellEditorListener) m_listeners.elementAt(k); l.editingCanceled(e); } removeEditor(); } public void addCellEditorListener(CellEditorListener l) { m_listeners.addElement(l); } public void removeCellEditorListener(CellEditorListener l) { m_listeners.removeElement(l); } public void actionPerformed(ActionEvent e) { stopCellEditing(); m_tree.stopEditing(); } }