I have a Java app that displays the users file system in a tree. I display the folder with a checkbox, icon and text. To do this I had to created a custom component for the tree cell. The component subclasses JLabel and contains JCheckBox and JLabel. I wrote my own renderer and editor to display and edit the component. When you click on the checkbox the first time it goes into edit mode but the code to turn off editing does not happen. All subsequent clicks on the checkbox work properly. I have done a lot of searching and cannot resolve this problem.
Here is the code for my renderer and editor. The tree has been set to allow editing and the renderer and editor are set.
class MyRenderer implements TreeCellRenderer
{
private CheckBoxPanel m_panel;
public MyRenderer()
{
m_panel = new CheckBoxPanel();
}
@Override
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
MyState state = (MyState)node.getUserObject();
m_panel.setState(state);
return m_panel;
}
}
class MyEditor extends AbstractCellEditor implements TreeCellEditor
{
private CheckBoxPanel m_panel;
private JCheckBox m_checkbox;
private MyState m_state;
public MyEditor()
{
m_panel = new CheckBoxPanel();
// m_panel.setColor(Color.red);
}
@Override
public Component getTreeCellEditorComponent(JTree tree,
Object value,
boolean isSelected,
boolean expanded,
boolean leaf,
int row) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
m_state = (MyState)treeNode.getUserObject();
m_panel.setState(m_state);
m_checkbox = m_panel.getCheckBox();
m_checkbox.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent e)
{
fireEditingStopped();
m_checkbox.removeItemListener(this);
}
});
return m_panel;
}
@Override
public Object getCellEditorValue()
{
m_state.setSelected(m_checkbox.isSelected());
return m_state;
}
@Override
public boolean isCellEditable(EventObject anEvent)
{
if (anEvent instanceof MouseEvent)
{
return true;
}
return false;
}
}
class CheckBoxPanel extends JPanel
{
private JCheckBox m_checkBox;
private JLabel m_label;
public CheckBoxPanel()
{
m_checkBox = new JCheckBox();
m_checkBox.setBackground(UIManager.getColor("Tree.background"));
m_checkBox.setBorder(null);
m_checkBox.setFocusable(true);
m_label = new JLabel();
m_label.setFont(UIManager.getFont("Tree.font"));
m_label.setFocusable(false);
setOpaque(false);
setLayout(new BorderLayout());
add(m_checkBox, BorderLayout.WEST);
add(m_label, BorderLayout.CENTER);
}
public JCheckBox getCheckBox()
{
return m_checkBox;
}
public void setState(MyState _state)
{
m_label.setText(_state.getText());
m_checkBox.setSelected(_state.isSelected());
}
public void setColor(Color _color)
{
m_label.setForeground(_color);
}
}
class MyState
{
private String m_text;
private boolean m_selected;
public MyState(String _text, boolean _selected)
{
m_text = _text;
m_selected = _selected;
}
public String getText()
{
return m_text;
}
public void setText(String _text)
{
m_text = _text;
}
public boolean isSelected()
{
return m_selected;
}
public void setSelected(boolean _selected)
{
m_selected = _selected;
}
}