steshor
steshor

Reputation: 13

Reload JTable's Object[][] after data has changed

I am wondering if it is possible to refresh a Table's GUI when the Object[][] used to initially populate it has changed.

Object[][] calculationsTableData;
public Interface() {
    ...
    analysisPanel.add(calculationsTable());
    ...
}

JScrollPane calculationsTable() {
    populateCalculationsTableData();
    ...
    calculationsTable = new JTable(calculationsTableData, calculationsColumnNames);
    ...
}

void populateCalculationsTableData(){
    Object[][] temp = new Object[x.numsSize][7];
    for (int i = 0; i < x.numsSize; i++) {
        temp[i][0] = df.format(x.nums[i]);
        ...
    }
    calculationsTableData = temp;
}

populateCalculationsTableData() is called when the x object has changed to repopulate calculationsTableData

repaint() and revalidate() methods do not appear to be effective in this scenario and neither does fireTableDataChanged() as this is not a table model.

Upvotes: 1

Views: 1879

Answers (2)

dic19
dic19

Reputation: 17971

By default JTable creates a new instance of DefaultTableModel AbstractTableModel [1] implementation if no table model is explicitely set. If the table needs to be updated you have to work with its model.

You could...

Set a new DefaultTableModel:

void populateCalculationsTableData() {
    ...
    calculationsTableData = temp;
    TableModel model = new DefaultTableModel(calculationsTableData, calculationsColumnNames);
    calculationsTable.setModel(model);
}

Or you could...

Create the table using a DefaultTableModel:

TableModel model = new DefaultTableModel(calculationsTableData, calculationsColumnNames);
calculationsTable = new JTable(model);

Cast the table model as DefaultTableModel and set its data and columns like this:

void populateCalculationsTableData() {
    ...
    calculationsTableData = temp;
    DefaultTableModel model = (DefaultTableModel)calculationsTable.getModel();
    model.setDataVector(calculationsTableData, calculationsColumnNames);
}

Suggested readings


[1]: After checking JTable(Object[][] rowData, Object[] columnNames) source code I've realized that no DefaultTableModel is created but a new anonymous inner class extending from AbstractTableModel instead.

Upvotes: 2

BarrySW19
BarrySW19

Reputation: 3809

I would create your own table model to wrap the object arrays, and which exposed the fireTableDataChanged() method:

private static class ObjectArrayModel extends AbstractTableModel {
    private final Object[][] rowData;
    private final Object[] columnNames;

    private ObjectArrayModel(Object[][] rowData, Object[] columnNames) {
        this.rowData = rowData;
        this.columnNames = columnNames;
    }

    @Override
    public void fireTableDataChanged() {
        super.fireTableDataChanged();
    }

    public String getColumnName(int column) {
        this.fireTableDataChanged();
        return columnNames[column].toString();
    }

    public int getRowCount() {
        return rowData.length;
    }

    public int getColumnCount() {
        return columnNames.length;
    }

    public Object getValueAt(int row, int col) { return rowData[row][col]; }

    public boolean isCellEditable(int row, int column) { return true; }

    public void setValueAt(Object value, int row, int col) {
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}

... when the data changes you should be able to call fireTableDataChanged() on this and it will notify the table it needs to redraw itself.

Upvotes: 2

Related Questions