Yeah I know, this sounds stupid. But before let me illustrate my problem.
I have a GUI with A LOT of JTable. I have various DefaultTableModel, one for each JTable. So, 1:1. And for each DefaultTableModel I have create one a TableModelListener.
For insert and delete elements in my GUI I have create only TWO methods, addVehicle and removeVehicle:
public void addVehicle(final DefaultTableModel model, final String s1, final String s2) {
Runnable addV = new Runnable() {
@Override
public void run() {
model.addRow(new Object[] { s1, s2 });
}
};
SwingUtilities.invokeLater(addV);
}
public void removeVehicle(final DefaultTableModel model, final int index) {
if (row!=null){
String s1= row.elementAt(0).toString();
Runnable removeV = new Runnable() {
@Override
public void run() {
model.removeRow(index);
}
};
SwingUtilities.invokeLater(removeV);
}
}
These methods are perfect, recognize automatically the right tablemodel.
But I have a necessity: since I have many JTable (and corresponding DefaultTableModels) and given that when I add/delete a row from a table a third-party software MUST BE INFORMED, I have created several TableModelListener.
For example listener1:
TableModelListener listener1 = new TableModelListener() {
public void tableChanged(TableModelEvent e) {
DefaultTableModel m = (DefaultTableModel) e.getSource();
int row = e.getLastRow();
switch (e.getType()) {
case (TableModelEvent.INSERT): {
System.out.println("Insert! Key: "+m.getValueAt(row, 0));
// My agent, the third-party software:
shipperAgent.newTruck((String) m.getValueAt(row, 0));
} break;
case (TableModelEvent.DELETE): {
System.out.println("Delete! Key:"+m.getValueAt(row, 0));
// My agent, the third-party software:
shipperAgent.removeTruck((String)m.getValueAt(row, 0));
} break;
case (TableModelEvent.UPDATE): {
// ...
} break;
}
}
};
Another example is listener 2 (I show you just a fragment...):
case (TableModelEvent.INSERT): {
System.out.println("Activate! Key: "+m.getValueAt(row, 0));
// My agent, the third-party software:
shipperAgent.activateTruck((String) m.getValueAt(row, 0));
} break;
case (TableModelEvent.DELETE): {
System.out.println("Deactivate! Key:"+m.getValueAt(row, 0));
// My agent, the third-party software:
shipperAgent.deactivateTruck((String)m.getValueAt(row, 0));
} break;
This is the problem: is all right for the insert, but not for the DELETE. I know why: when I remove a row from the GUI, the row is deleted and in the switch (case TableModelEvent.DELETE) work on another row (that immediately after the one that I deleted). Moreover, if this row is the last (since there are no more lines after) i get a NullPointerException.
HOW I CAN, in the listener, to use a row BEFORE it is actually removed? (or other brilliant ways?)