Java tutorial
import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.Enumeration; import java.util.EventObject; import javax.swing.AbstractCellEditor; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.WindowConstants; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; public final class Main { public static JComponent makeUI() { JTree tree = new JTree(); TreeModel model = tree.getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); Enumeration e = root.breadthFirstEnumeration(); while (e.hasMoreElements()) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.nextElement(); Object o = node.getUserObject(); if (o instanceof String) { node.setUserObject(new CheckBoxNode((String) o, false)); } } tree.setEditable(true); tree.setCellRenderer(new CheckBoxNodeRenderer()); tree.setCellEditor(new CheckBoxNodeEditor()); tree.expandRow(0); return new JScrollPane(tree); } public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new Main().makeUI()); f.setSize(320, 240); f.setVisible(true); } } class CheckBoxNode { public final String text; public final boolean selected; public CheckBoxNode(String text, boolean selected) { this.text = text; this.selected = selected; } @Override public String toString() { return text; } } class CheckBoxNodeRenderer implements TreeCellRenderer { DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); JCheckBox check = new JCheckBox(); JPanel p = new JPanel(new BorderLayout()); public CheckBoxNodeRenderer() { p.setFocusable(false); p.setOpaque(false); p.add(check, BorderLayout.WEST); check.setOpaque(false); } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { JLabel l = (JLabel) renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); if (value instanceof DefaultMutableTreeNode) { check.setEnabled(tree.isEnabled()); check.setFont(tree.getFont()); Object userObject = ((DefaultMutableTreeNode) value).getUserObject(); if (userObject instanceof CheckBoxNode) { CheckBoxNode node = (CheckBoxNode) userObject; l.setText(node.text); check.setSelected(node.selected); } p.add(l); return p; } return l; } } class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor { DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); JCheckBox check = new JCheckBox(); JPanel p = new JPanel(new BorderLayout()); String str = null; public CheckBoxNodeEditor() { super(); check.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { stopCellEditing(); } }); p.setFocusable(false); p.setRequestFocusEnabled(false); p.setOpaque(false); p.add(check, BorderLayout.WEST); check.setOpaque(false); } @Override public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { JLabel l = (JLabel) renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true); if (value instanceof DefaultMutableTreeNode) { Object userObject = ((DefaultMutableTreeNode) value).getUserObject(); if (userObject instanceof CheckBoxNode) { CheckBoxNode node = (CheckBoxNode) userObject; l.setText(node.text); check.setSelected(node.selected); str = node.text; } p.add(l); return p; } return l; } @Override public Object getCellEditorValue() { return new CheckBoxNode(str, check.isSelected()); } @Override public boolean isCellEditable(EventObject e) { if (e instanceof MouseEvent && e.getSource() instanceof JTree) { MouseEvent me = (MouseEvent) e; JTree tree = (JTree) e.getSource(); TreePath path = tree.getPathForLocation(me.getX(), me.getY()); Rectangle r = tree.getPathBounds(path); if (r == null) { return false; } Dimension d = check.getPreferredSize(); r.setSize(new Dimension(d.width, r.height)); if (r.contains(me.getX(), me.getY())) { check.setBounds(new Rectangle(0, 0, d.width, r.height)); return true; } } return false; } }