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.




