A JTree uses TreeCellRenderer and TreeCellEditor to display three custom nodes:
- a single JCheckBox
- a single JButton
- a JPanel composed by any action Component (here is a JCheckBox on North and a JButton on South)
screenshot: https://i.stack.imgur.com/ZNMDx.png
There is no problem with such a tree if you use Java Runtime Environment 6.
Besides using Java Runtime Environment 7, my problem occurs when I click on the JButton inside the JPanel node. The 'click' animation for JButton is not rendered the first time you click in JPanel (and after each time the node with JPanel stops being edited). The first node JCheckBox and the second node JButton are working perfectly with jre6 and jre7 either.
I would like to make it work exactly like before in jre6, is there a workaround?
Note: it's not a problem on making a button perform your code.
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
class TreeNodeModel{
public boolean isJCheckBox = false;
public boolean isJButton = false;
public boolean isJPanel = false;
public Component userObject = null;
public TreeNodeModel(String name){
if( name.equals("JCheckBox") ){
isJCheckBox = true;
}else if( name.equals("JButton") ){
isJButton = true;
}else if( name.equals("JPanel") ){
isJPanel = true;
}
}
}
class CustomTreeCellRenderer implements TreeCellRenderer{
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component returnValue = null;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof TreeNodeModel) {
TreeNodeModel node = (TreeNodeModel) userObject;
if(node.isJButton){
returnValue = new JButton("Ok");
}else if(node.isJCheckBox){
returnValue = new JCheckBox("Ok");
}else{
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JButton("Problem"), BorderLayout.SOUTH);
panel.add(new JCheckBox("Problem"), BorderLayout.NORTH);
returnValue = panel;
}
}
}
if(returnValue == null)
returnValue = new DefaultTreeCellRenderer().getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
return returnValue;
}
}
class CustomTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
Component returnValue = null;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof TreeNodeModel) {
TreeNodeModel node = (TreeNodeModel) userObject;
if(node.isJButton){
returnValue = new JButton("Ok");
}else if(node.isJCheckBox){
returnValue = new JCheckBox("Ok");
}else{
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JButton("Problem"), BorderLayout.SOUTH);
panel.add(new JCheckBox("Problem"), BorderLayout.NORTH);
returnValue = panel;
}
}
}
return returnValue;
}
@Override
public Object getCellEditorValue() { return null; }
}
public class MyTestRendererEditor extends JFrame {
public MyTestRendererEditor() {
DefaultMutableTreeNode node = new DefaultMutableTreeNode("root");
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JCheckBox")));
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JButton")));
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JPanel")));
final JTree tree = new JTree(new DefaultTreeModel(node));
tree.setCellRenderer(new CustomTreeCellRenderer());
tree.setCellEditor(new CustomTreeCellEditor());
tree.setEditable(true);
getContentPane().add(new JScrollPane(tree));
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyTestRendererEditor();
}
});
}
}