I think stopping the selection of the actual in the shouldSelectCell() method is a kind of workaround for this, and converting mouse events seems weird.
Instead, a much cleaner approach would be to make the checkbox not fill the entire cell, so that it will only be selected if you click directly on the "checkbox" part.
You can do this by placing the JCheckbox inside the JPanel and centering it without stretching it. To do this, we can make the layout manager JPanel a GridBagLayout . See how when using GridBagLayout internal content is not stretched:
(from fooobar.com/questions/398771 / ... )
So, if you click on the empty space around it, you will click on JPanel , so you will not change the value of JCheckbox .
The code for your CheckBoxEditor is ultimately obtained as follows:
class CheckBoxEditor extends AbstractCellEditor implements TableCellEditor { private static final long serialVersionUID = 1L; private final JPanel componentPanel; private final JCheckBox checkBox; public CheckBoxEditor() { componentPanel = new JPanel(new GridBagLayout());
(Note that you can no longer renew with DefaultCellEditor - in the code above you now need to switch from AbstractCellEditor and implement TableCellEditor ).
I think this version of your CheckBoxEditor does what you want - if you click into the empty space around this checkbox, nothing will happen. The checkbox will be checked only when you click on it.
Also, using JPanel , you don't need to do any MouseEvent calculations and (at least for me), the code looks a lot cleaner, and it's easier to see what happens.
EDIT1:
I read your comment and I found a solution: why not leave the editor as it is, but then just create a cell DefaultTableCellRenderer that comes from DefaultTableCellRenderer ? Then in CheckBoxEditor use the same borders and backgrounds as the rendering.
This should provide the desired effect (I translated the general code into methods of the outer class, so I do not need to repeat them):
private static void setCheckboxValue(JCheckBox checkBox, Object value) { if (value instanceof Boolean) { checkBox.setSelected(((Boolean) value).booleanValue()); } else if (value instanceof String) { checkBox.setSelected(value.equals("true")); } } private static void copyAppearanceFrom(JPanel to, Component from) { if (from != null) { to.setOpaque(true); to.setBackground(from.getBackground()); if (from instanceof JComponent) { to.setBorder(((JComponent) from).getBorder()); } } else { to.setOpaque(false); } } class CheckBoxEditor extends AbstractCellEditor implements TableCellEditor { private static final long serialVersionUID = 1L; private final JPanel componentPanel; private final JCheckBox checkBox; public CheckBoxEditor() { componentPanel = new JPanel(new GridBagLayout());
Then you should set the render with the editor in your constructor:
checkboxColumn.setCellEditor(new CheckBoxEditor()); checkboxColumn.setCellRenderer(new CheckBoxRenderer());
Here are some screenshots comparing the two methods:
Your original method:; JPanel and JCheckbox :


I can barely see the difference :)
IMHO, I still think that just using a simple Java API table is cleaner than calculating mouse pointer checks, but the choice is up to you.
I hope this helps!
EDIT2:
Also, if you want to switch using a space, I think you can just add the key binding to componentPanel in the CheckBoxEditor constructor:
class CheckBoxEditor extends AbstractCellEditor implements TableCellEditor {
I'm not sure if you can use drag-and-drop with boolean values. I tried to drag "true" to the checkboxes in the original version, but nothing happened, so I don't think you need to worry about DnD.