JTable disable Checkbox in Cell

Solution 1:

As noted in Concepts: Editors and Renderers, "a single cell renderer is generally used to draw all of the cells that contain the same type of data." You'll need to maintain the enabled state in your table model.

Addendum: As a concrete example, the data model in this example is a simple array of Date instances. Overriding getTableCellRendererComponent() as shown below causes odd days to be disabled. In this case, being odd is a property inherent to the Date value itself, but the model could be queried for any related property at all.

disabled image

@Override
public Component getTableCellRendererComponent(JTable table,
    Object value, boolean isSelected, boolean hasFocus, int row, int col) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime((Date) value);
    Component c = super.getTableCellRendererComponent(
        table, value, isSelected, hasFocus, row, col);
    c.setEnabled(calendar.get(Calendar.DAY_OF_MONTH) % 2 == 0);
    return c;
}

Addendum: In the example above, the DateRenderer is evoked because the TableModel returns the type token Date.class, for which it has been made the default.

table.setDefaultRenderer(Date.class, new DateRenderer());

An identical appearance can be obtained by overriding prepareRenderer() as shown below, but the method is invoked for all cells, irrespective of class. As a result, prepareRenderer() is ideal for affecting entire rows, as shown in Table Row Rendering.

private final JTable table = new JTable(model) {

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
        Component c = super.prepareRenderer(renderer, row, col);
        if (col == DATE_COL) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime((Date) model.getValueAt(row, col));
            c.setEnabled(calendar.get(Calendar.DAY_OF_MONTH) % 2 == 0);
        }
        return c;
    }
};