I`ve got a mysterious problem with my custom JTable and a custom TableRenderer. In 95%-99,99% it works perfectly, but sometimes the renderer just stops doing his job, and leaves a portion of the table (which is inside a JScrollPane) blank.
The problem case looks like that:
In all other cases, and after a slight resize of the window, the Table look like that:
Now both columns has a TextAreaCellRenderer associated to, which works as follows:
public class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
private final Color evenColor = new Color(252, 248, 202);
public TextAreaCellRenderer() {
super();
setLineWrap(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
setBackground((row % 2 == 0) ? evenColor : getBackground());
}
setWrapStyleWord(true);
setFont(table.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}
I also have to override the doLayout method of the JTable to be able to calculate the hight of a cell depending on the content. The custom table looks like that:
public class MediaMetaDataTable extends JTable {
@Override
public void doLayout() {
TableColumn col = getColumnModel().getColumn(1);
for (int row = 0; row < getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, 1);
if (c instanceof JTextArea) {
JTextArea a = (JTextArea) c;
int h = getPreferredHeight(a) + getIntercellSpacing().height;
if (getRowHeight(row) != h) {
setRowHeight(row, h);
}
}
}
super.doLayout();
}
private int getPreferredHeight(final JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
}
The table is instantiated once with the following parameters:
metaTable = new MediaMetaDataTable();
metaTable.setModel(new MediaMetaDataTableModel());
metaTable.setEnabled(false);
metaTable.setShowGrid(false);
metaTable.setTableHeader(null);
metaTable.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
metaTable.getColumnModel().getColumn(1).setCellRenderer(new TextAreaCellRenderer());
metaTable.setPreferredScrollableViewportSize(new Dimension(-1, -1));
metaTable.setShowHorizontalLines(false);
metaTable.setShowVerticalLines(false);
Each time the data to show changes i update table by replacing the underlying models data:
List<MediaMetaData> metaInformation = mediaSearchHit.getMetaInformation();
if (metaInformation != null) {
((MediaMetaDataTableModel) metaTable.getModel()).replaceMetaInfos(metaInformation);
}
On update the model itself fires a table data changed event:
public class MediaMetaDataTableModel extends AbstractTableModel {
private List<MediaMetaData> metaInfos = new LinkedList<MediaMetaData>();
public static final int COL_INDEX_NAME = 0;
public static final int COL_INDEX_VALUE = 1;
public void replaceMetaInfos(final List<MediaMetaData> metaInfos) {
this.metaInfos = null;
this.metaInfos = metaInfos;
fireTableDataChanged();
}
...
Now does anybody has a idea, what causes the described rendering problem?
Thanks for any advices.