JTable不会在fireTableChanged上刷新

时间:2019-01-30 15:13:28

标签: java swing jtable

我们在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);
            }
        }
    }

谢谢大家。抱歉造成干扰。

1 个答案:

答案 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(...)方法,它将为您调用模型。