【发布时间】:2013-12-02 15:44:26
【问题描述】:
我的自定义 JTable 和自定义 TableRenderer 出现了一个神秘问题。 在 95%-99,99% 的情况下,它可以完美运行,但有时渲染器会停止工作,并将表格的一部分(位于 JScrollPane 内)留空。
问题案例如下所示:
在所有其他情况下,稍微调整窗口大小后,表格如下所示:
现在两列都有一个与之关联的 TextAreaCellRenderer,其工作原理如下:
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;
}
}
我还必须重写 JTable 的 doLayout 方法,以便能够根据内容计算单元格的高度。自定义表格如下所示:
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;
}
}
该表使用以下参数实例化一次:
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);
每次要显示的数据发生变化时,我都会通过替换底层模型数据来更新表:
List<MediaMetaData> metaInformation = mediaSearchHit.getMetaInformation();
if (metaInformation != null) {
((MediaMetaDataTableModel) metaTable.getModel()).replaceMetaInfos(metaInformation);
}
更新模型本身会触发表数据更改事件:
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();
}
...
现在有人知道,是什么导致了所描述的渲染问题?
感谢您的任何建议。
【问题讨论】:
-
如需尽快获得更好的帮助,请发帖SSCCE。
-
有时建议同步不正确。
-
现在有人知道,是什么导致了所描述的渲染问题? == SSCCE,简短,可运行,可与 JTable 的硬编码值编译,顺便说一句,昨天被问及回答了类似的问题
-
并创建一个局部变量而不是extends JTextArea,doLayout很熟悉,重要错误的原因是setPreferredScrollableViewportSize(new Dimension(-1, -1));,开始搜索如何编写AbstractTableModel if rest 与您在此处显示的代码片段相同
标签: java swing jtable rendering