In my experience, it's better to get the DefaultTableCellHeaderRenderer
when you overwrite any JTable
Renderer
. So, instead of messing with the JLabel
from the Renderer
directly, you grab the Renderer
with super()
. So, your code should look like this:
header.setDefaultRenderer(new DefaultTableCellHeaderRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellHeaderRenderer rendererComponent = (DefaultTableCellHeaderRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (selectedColumn == value) {
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createLineBorder(Color.red, 1)));
rendererComponent.setHorizontalAlignment(SwingConstants.LEFT);
} else {
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 0)));
rendererComponent.setHorizontalAlignment(SwingConstants.CENTER);
}
if (column == 0) {
rendererComponent.setForeground(Color.red);
} else {
rendererComponent.setForeground(header.getForeground());
}
return rendererComponent;
}
});
To try and answer your questions directly:
Question 1:
Q: How do I correctly use customer renderers to paint specific cells in a JTable?
A: Your current code is setting a Renderer
on the JTableHeader
. To add a Renderer on your table cells would be similar code to what's above, only you'd set it through the Column model:
table.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// Set your code to render your component.
return renderer;
}
});
Note about this: JTables
are column-based, which means that all the data in a certain column must be the same type (your SSCCE follows this convention). My favorite thing to do is to provide a custom Renderer
for each type. For example, whenever I have a Date
column, I use this renderer:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import org.joda.time.LocalDate;
/**
*
* @author Ryan
*/
public class DateCellRenderer extends DefaultTableCellRenderer {
String pattern;
public DateCellRenderer(String pattern){
this.pattern = pattern;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value != null && value instanceof LocalDate) {
renderer.setText(((LocalDate)value).toString(pattern));
} else
throw new IllegalArgumentException("Only supported Object type is LocalDate.");
return renderer;
}
}
And I call this code with something similar:
table.getColumn("Date Entered").setCellRenderer(new DateCellRenderer("MMM dd, yyyy"));
Question 2:
Q: particular one table header color java swing
A: Umm.. Your SSCCE seems to have it figured out.
Question 3:
Q: about super.getTableCellRendererComponent(...) must be last code line before returns, I'm not able to write correct Renderer by those suggestion, for me works only this way
A: I'm not sure what you mean "must be last code line before returns." That is not the case, proven by the code snip I gave above
Question 4:
Q: JLabel is added for Borders, HorizontalAlignment and Foreground, especially Background caused me a few non_senses by using Component instead of JLabel, (not important here somehow)
A: Ok... the DefaultTableCellHeaderRenderer
is sufficient for all of those, borders, alignment, foreground and background.