I'm writing a Java program that uses JTable and AbstractTableModel. As usual, I like to improvise, I like to add features following the inspiration. This time I wanted to create a table with static data, but at a certain point...hey, why not adding data dynamically?
This way of life is funny but can create a lot of problems: I'm stubborn and I want to fix them.
This way of life is funny but can create a lot of problems: I'm stubborn and I want to fix them.
"Every table object uses a table model object to manage the actual table data. A table model object must implement the TableModel interface. If the programmer does not provide a table model object, JTable automatically creates an instance of DefaultTableModel."
DefaultTableModel can easily add/remove a row, but what happens if we want to use AbstractTableModel?
I browsed the internet but I wasn't able to find a solution: people suggest to use DefaultTableModel (too easy), to call the superclass method fireTableRowsInserted(), or fireTableDataChanged() and fireTableRowsUpdated(int firstRow, int lastRow)...
These solutions don't work for me.
I found a fix experimenting a lot of ideas but the solution is quite easy: we have to pass the new data to the AbstractTableModel and call:
table.revalidate();
table.repaint();
tableModel.fireTableDataChanged();
tableModel.fireTableDataChanged();
That's all! Below a concrete example, the code I'm using:
import java.stuff...
private JTable table;
private Object[][] newData, oldData;
MyTableModel myTableModel;
public myClass() {
newData = {{"Kathy", "Smith",
"Snowboarding", new Integer(5), new Boolean(false)},
{"John", "Doe",
"Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black",
"Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White",
"Speed reading", new Integer(20), new Boolean(true)},
{"Joe", "Brown",
"Pool", new Integer(10), new Boolean(false)}
myTableModel = new MyTableModel();
myTableModel.setData(newData);
table = new JTable(myTableModel);
// add features to the table here
}
/**
* This method adds a row to the table. We have to
* append the new row to the existing data, pass new
* data to AbstractTableModel
*/
private void addRow() {
oldData = newData;
newData = new Object[oldData.length + 1][];
// Copy old data to new data
for (int x = 0; x < oldData.length; x++) {
newData[x] = oldData[x];
}
// Append new row
newData[oldData.length] = new Object[]{new Boolean(true)};
// Pass the new data to the table model
myTableModel.setModelData(newData);
// Update the table
table.revalidate();
table.repaint();
myTableModel.fireTableDataChanged();
}
class MyTableModel extends AbstractTableModel {
// Static column Names
private String[] columnNames = {"bla", "bla", "bla",
"bla", "bla"};
// Data to populate the table
private Object[][] data;
public void setData(Object[][] data){
this.data = data;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return data.length;
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
@Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int row, int col) {
return true;
}
@Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
I apologize if blogspot doesn't format the code in the right way and I hope this solution will work for you as it does for me.
Best regards.