我们在JTable中具有相当复杂的模型。在新开发中,我注意到当我为单个单元格调用fireTableChanged(...)时,GUI不会刷新。
所以我的问题是:
我要在TableModelEvent中添加什么-模型行ID或视图行ID?
查看JTable代码(我有jdk1.8.0_202):
public class JTable extends JComponent implements TableModelListener, Scrollable,
...
public void tableChanged(TableModelEvent e) {
...
int modelColumn = e.getColumn();
int start = e.getFirstRow();
int end = e.getLastRow();
Rectangle dirtyRegion;
if (modelColumn == TableModelEvent.ALL_COLUMNS) {
// 1 or more rows changed
dirtyRegion = new Rectangle(0, start * getRowHeight(),
getColumnModel().getTotalColumnWidth(), 0);
}
else {
// A cell or column of cells has changed.
// Unlike the rest of the methods in the JTable, the TableModelEvent
// uses the coordinate system of the model instead of the view.
// This is the only place in the JTable where this "reverse mapping"
// is used.
int column = convertColumnIndexToView(modelColumn);
dirtyRegion = getCellRect(start, column, false);
}
我看到为了计算脏区,它会转换列索引,但对行却不这样做。
“反向映射”注释是什么意思?
看起来像是Swing中的错误。
你觉得呢?
更新
我的代码很简单:
model.fireTableChanged(new TableModelEvent(model, rowNumber, rowNumber, columnNumber));
GUI不会刷新单元格。
UPDATE2
问题出在我的模型中,太复杂了,无法在此处发布。 :(
我不能怪JTable。它是以此方式设计的。唯一可能的添加是RowSorter,并且在那里可以正确转换:
private void repaintSortedRows(ModelChange change) {
...
int modelIndex = change.startModelIndex;
while (modelIndex <= change.endModelIndex) {
int viewIndex = convertRowIndexToView(modelIndex++);
if (viewIndex != -1) {
Rectangle dirty = getCellRect(viewIndex, columnViewIndex,
false);
int x = dirty.x;
int w = dirty.width;
if (eventColumn == TableModelEvent.ALL_COLUMNS) {
x = 0;
w = getWidth();
}
repaint(x, dirty.y, w, dirty.height);
}
}
}
谢谢大家。抱歉造成干扰。
答案 0 :(得分:1)
我的代码很简单:
model.fireTableChanged(new TableModelEvent(model, rowNumber, rowNumber, columnNumber));
这不是更改JTable中数据的方式。您不应该直接调用该方法。更改数据时,TableModel负责调用该方法。
使用TableModelListener的目的是侦听TableModel中的更改。如我在评论中提供的链接所示,在数据更改后,如果要进行特殊处理,则只需实现侦听器。
如果现有单元格中有数据,并且想要更改其值,则可以执行以下操作:
model.setValueAt("new value", 0, 0);
如果要添加新的数据行,请使用:
model.addRow(...);
重点是所有更改都应通过TableModel完成。
请注意,JTable还具有便捷的setValueAt(...)方法,它将为您调用模型。