Making a GUI in Swing (NetBeans 15, Sun JDK 19.0.1), i'm trying to set custom background color for JTable rows and encountered issues with boolean cells, and i can't seem to be able to make the background uniform across all cells. Please note that the following code tries to paint the background for the whole table, but my target is to set the background for one line at a time; this code serves the only purpose of highlighting the weird interaction between Nimbus alternate row coloring and the custom renderers i have personally encountered.
The issue seems vastly documented already, here's what i tried:
First attempt using a custom renderer, like so:
class MyTableRenderer implements TableCellRenderer {
private final TableCellRenderer renderer;
public MyTableRenderer(TableCellRenderer renderer) {
this.renderer = renderer;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//c.setOpaque(true);
c.setBackground(Color.red);
return c;
}
}
and got this result:

Uncommenting the c.setOpaque(true); line yields the following:

Second attempt, by means of the method PrepareRenderer() as documented here, and i made it this way:
tbl_Correction = new JTable() {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
//((JComponent)c).setOpaque(true);
c.setBackground(Color.red);
return c;
}
};
got the exact same behavior as before, down to the detail of uncommenting the setOpaque line.
Further reading revealed that the alternate table row coloring is handled by the Nimbus Look&Feel, which NetBeans IDE configured automagically upon creation of the project, so i tried adding this line after the Nimbus configuration:
UIManager.getLookAndFeelDefaults().put("Table.alternateRowColor", Color.GREEN);
which led to this 
and to the conclusion that Nimbus might be interfering with the intended cell rendering.
Indeed, removing Nimbus altogether gives me the result i want, but sends the rest of the UI back to the middle ages...
Oddly enough, if i select a cell, the whole row gets the correct background, including the boolean cells:

The last relevant piece of info i found is this, in the javadoc for the setBackground() method: It is up to the look and feel to honor this property, some may choose to ignore it. which made me dubious this can even work withoud swapping Nimbus for something else.
My conclusion: no matter where i put the rendering instructions, i can only manage to change the background of the booleans that are not on one of the alternating rows, unless the row is selected.
The question: did i miss some major obvious configuration step? Or perhaps is there a way to disable Nimbus's Table alternating row colors? Or again, is this some sort of known issue?
(more SO answers: this is not relevant; this does not work;)
Edit: added SSCCE, though being GUI code made from the IDE is far from short.
package tabletest;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class NewJFrame extends javax.swing.JFrame {
public NewJFrame() {
initComponents();
// attempt #1
/*
jTable1.setDefaultRenderer(Boolean.class, new MyTableRenderer(jTable1.getDefaultRenderer(Boolean.class)));;
jTable1.setDefaultRenderer(String.class, new MyTableRenderer(jTable1.getDefaultRenderer(String.class)));;
*/
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable() {
//attempt #2
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
//((JComponent)c).setOpaque(true);
c.setBackground(Color.red);
return c;
}
}
;
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{ new Boolean(true), new Integer(1), new Float(0.1), "asd"},
{ new Boolean(true), new Integer(2), new Float(0.2), "lol"},
{null, new Integer(3), new Float(0.3), "xd"},
{null, new Integer(4), new Float(0.4), "ftw"},
{null, new Integer(5), new Float(0.5), "wtf"}
},
new String [] {
"bool", "int", "float", "string"
}
) {
Class[] types = new Class [] {
java.lang.Boolean.class, java.lang.Integer.class, java.lang.Float.class, java.lang.String.class
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
});
jScrollPane1.setViewportView(jTable1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(59, 59, 59)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(174, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(25, 25, 25)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(100, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
//attempt #1
class MyTableRenderer implements TableCellRenderer {
private final TableCellRenderer renderer;
public MyTableRenderer(TableCellRenderer renderer) {
this.renderer = renderer;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//c.setOpaque(true);
c.setBackground(Color.red);
return c;
}
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
// End of variables declaration
}
You wrote in your question (regarding the code in your question):
This is what I set out to do. However, you also wrote:
Then I tried a different approach – which still paints the entire background red but I'm hoping you will be able to adapt the below code to suit your requirements.
First Approach
As detailed here:
https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/color.html
and here:
https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html
Simply setting the appropriate properties, in class
UIManager, achieves [what I believe to be] your desired result, i.e. making the entireJTablebackground red. This works for all columns apart from the first column of theJTablethat displaysBooleanvalues. For that, I created a custom [table] cell renderer, based on the one used by Nimbus look-and-feel, namely:Here is the code for that renderer:
I also wrote a custom
TableModel.Here is the code for this first approach:
Second Approach
This approach does not modify
UIManagerdefaults but instead overrides methodprepareRenderer(in classJTable). Note that this approach also uses the sameTableModeland custom renderer that the first approach used.I overrode method
prepareRendererrather than creating another custom renderer that would be based on the generalJTablecell renderer used by Nimbus look-and-feel since that renderer is much more complex thanSynthBooleanTableCellRenderer.Here is the code for the second approach: