here you can find answer why (JButtons JComponents) JCheckBox and JRadioButton ... are little bit different for Rendering in the TableCell as another JComponents (and you have to play with JTable row Selection because I changed Opacity)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class CheckboxInCellTest {
private String[] columnNames = {"Boolean(Default)", "Boolean"};
private Object[][] data = {{false, true}, {true, false}, {false, true}};
private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
@Override
public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
public JComponent makeUI() {
JTable table = new JTable(model);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
JTable t = (JTable) e.getComponent();
Point pt = e.getPoint();
int row = t.rowAtPoint(pt), col = t.columnAtPoint(pt);
if (t.convertColumnIndexToModel(col) == 1) {
t.getCellEditor(row, col).stopCellEditing();
}
}
});
table.setRowHeight(20);
CheckBoxEditorRenderer1 cer = new CheckBoxEditorRenderer1();
table.getColumnModel().getColumn(1).setCellRenderer(cer);
table.getColumnModel().getColumn(1).setCellEditor(cer);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new CheckboxInCellTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class CheckBoxPanel1 extends JPanel {
private static final long serialVersionUID = 1L;
public final JCheckBox button = new JCheckBox();
CheckBoxPanel1() {
super(new GridBagLayout());
add(button);
button.setOpaque(false);
setOpaque(false);
}
}
class CheckBoxEditorRenderer1 extends AbstractCellEditor implements TableCellRenderer, TableCellEditor {
private static final long serialVersionUID = 1L;
private final CheckBoxPanel1 editor = new CheckBoxPanel1();
private final CheckBoxPanel1 renderer = new CheckBoxPanel1();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean is, boolean hf, int row, int column) {
renderer.button.setSelected(Boolean.TRUE.equals(value));
renderer.button.setOpaque(is);
return renderer;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
editor.button.setSelected(Boolean.TRUE.equals(value));
renderer.button.setOpaque(isSelected);
return editor;
}
@Override
public Object getCellEditorValue() {
return editor.button.isSelected();
}
}
and with JButton in the TableCell ... with Nimbus L&F (required Java > 1.6.17 ??? now I have xxx.25)
import com.sun.java.swing.Painter;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.util.LinkedList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import sun.swing.table.DefaultTableCellHeaderRenderer;
public class TableButtonTest extends JFrame {
private static final long serialVersionUID = 1L;
public TableButtonTest() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable table = new JTable(new TestModel());
table.getTableHeader().setReorderingAllowed(false);
table.setRowHeight(20);
table.getColumnModel().getColumn(1).setPreferredWidth(3);
table.getColumnModel().getColumn(2).setPreferredWidth(3);
table.getTableHeader().setDefaultRenderer(new WrappingRenderer(table.getTableHeader()));
this.add(new JScrollPane(table));
Action increase = new AbstractAction("+") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
JTable table = (JTable) e.getSource();
int row = Integer.valueOf(e.getActionCommand());
TestModel model = (TestModel) table.getModel();
model.increment(row, 0);
//model.fireTableCellUpdated(row, 0);
}
};
ButtonColumn inc = new ButtonColumn(table, increase, 1);
Action decrease = new AbstractAction("-") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
JTable table = (JTable) e.getSource();
int row = Integer.valueOf(e.getActionCommand());
TestModel model = (TestModel) table.getModel();
model.decrement(row, 0);
}
};
ButtonColumn dec = new ButtonColumn(table, decrease, 2);
JTableHeader tbh = table.getTableHeader();
tbh.setOpaque(false);
Painter painter = new com.sun.java.swing.Painter() {
public void paint(Graphics2D g, Object o, int w, int h) {
}
};
javax.swing.UIDefaults defaults = new javax.swing.UIDefaults();
defaults.put("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter", painter);
defaults.put("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter",
defaults.get(("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter")));
tbh.putClientProperty("Nimbus.Overrides", defaults);
tbh.putClientProperty("Nimbus.State", "Pressed");
tbh.putClientProperty("JTree.lineStyle", "Angled");
setLocation(200, 200);
pack();
}
private static class WrappingRenderer implements TableCellRenderer {
private DefaultTableCellHeaderRenderer delegate;
private JTableHeader header;
public WrappingRenderer(JTableHeader header) {
this.header = header;
this.delegate = (DefaultTableCellHeaderRenderer) header.getDefaultRenderer();
header.setDefaultRenderer(this);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
TableColumn draggedColumn = table.getTableHeader().getDraggedColumn();
if (isSelected) {
comp.setBackground(table.getSelectionBackground());
} else {
comp.setBackground(table.getBackground());
}
if (draggedColumn != null) {
if (table.convertColumnIndexToModel(column) == draggedColumn.getModelIndex()) {
setNimbusState("Pressed");
} else {
setNimbusState(null);
}
} else {
setNimbusState(null);
}
// do similar for resizing column
return comp;
}
public void setNimbusState(String state) {
delegate.putClientProperty("Nimbus.State", state);
}
}
public static void main(String[] args) {
try {
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
new TableButtonTest().setVisible(true);
}
}
class TestModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private List<TestRecord> records = new LinkedList<TestRecord>();
private static class TestRecord {
private int val = 0;
}
public void increment(int row, int col) {
records.get(row).val++;
fireTableCellUpdated(row, col);
}
public void decrement(int row, int col) {
records.get(row).val--;
fireTableCellUpdated(row, col);
}
public TestModel() {
records.add(new TestRecord());
records.add(new TestRecord());
}
@Override
public Class<?> getColumnClass(int col) {
switch (col) {
case 0:
return Integer.class;
case 1:
return ButtonColumn.class;
case 2:
return Boolean.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int row, int col) {
return true;
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public int getRowCount() {
return records.size();
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return records.get(row).val;
} else if (col == 1) {
return "+";
} else {
return "-";
}
}
}