import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.EventObject;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.CellEditorListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
@SuppressWarnings("serial")
public class TreeCheckEditorRendererDemo extends JFrame {
private JTree tree;
private DefaultTreeModel model;
public TreeCheckEditorRendererDemo() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode node = new DefaultMutableTreeNode("anothernode");
root.add(node);
node.add(new DefaultMutableTreeNode(new CheckableTreeNodeObject("child1")));
node.add(new DefaultMutableTreeNode(new CheckableTreeNodeObject("child2")));
root.add(new DefaultMutableTreeNode(new CheckableTreeNodeObject("child3")));
model = new DefaultTreeModel(root);
tree = new JTree(model);
Icon icon = createDummyIcon();
tree.setCellRenderer(new CustomRenderer(icon));
tree.setCellEditor(new CustomEditor(tree, icon));
tree.setEditable(true);
this.getContentPane().add(tree);
}
private static Icon createDummyIcon() {
BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.RED);
g.fillRect(0, 0, 15, 15);
g.setColor(Color.BLUE);
g.fillRect(5, 5, 15, 15);
g.dispose();
return new ImageIcon(img);
}
class CheckableTreeNodeObject {
private String text;
private boolean selected;
public CheckableTreeNodeObject(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
class CustomRenderer extends DefaultTreeCellRenderer {
private JPanel panel;
private JCheckBox box;
private JLabel label;
public CustomRenderer(Icon icon) {
panel = new JPanel();
panel.add(box = new JCheckBox());
panel.add(new JLabel(icon));
panel.add(label = new JLabel());
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
if (treeNode.getUserObject() instanceof CheckableTreeNodeObject) {
CheckableTreeNodeObject o = (CheckableTreeNodeObject)treeNode.getUserObject();
box.setSelected(o.isSelected());
label.setText(o.getText());
return panel;
}
this.setIcon(null);
return this;
}
}
class CustomEditor implements TreeCellEditor {
private JTree tree;
private CheckableTreeNodeObject ctno;
private JPanel panel;
private JCheckBox box;
private JTextField field;
public CustomEditor(JTree tree, Icon icon) {
this.tree = tree;
panel = new JPanel();
panel.add(box = new JCheckBox());
panel.add(new JLabel(icon));
panel.add(field = new JTextField());
box.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (ctno!=null)
ctno.setSelected(box.isSelected());
}
});
field.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent evt) {
if (evt.getKeyChar()==KeyEvent.VK_ENTER) {
if (ctno!=null)
ctno.setText(field.getText());
CustomEditor.this.tree.stopEditing();
}
}
});
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded,
boolean leaf, int row) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
if (treeNode.getUserObject() instanceof CheckableTreeNodeObject) {
ctno = (CheckableTreeNodeObject)treeNode.getUserObject();
box.setSelected(ctno.isSelected());
field.setText(ctno.getText());
return panel;
}
ctno = null;
return null;
}
public Object getCellEditorValue() {
return ctno;
}
public boolean isCellEditable(EventObject evt) {
if (evt instanceof MouseEvent) {
MouseEvent me = (MouseEvent)evt;
DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getPathForLocation(me.getX(), me.getY()).getLastPathComponent();
return node.getUserObject() instanceof CheckableTreeNodeObject;
}
return false;
}
public boolean stopCellEditing() {
return true;
}
public void addCellEditorListener(CellEditorListener l) {
}
public void cancelCellEditing() {
}
public void removeCellEditorListener(CellEditorListener l) {
}
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
}
public static void main(String[] args) {
JFrame frame = new TreeCheckEditorRendererDemo();
frame.setBounds(0, 0, 500, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}