JTable Input Verifier
First: input validation on JTable editing is not well supported. A couple of comments
- tableChanged in a TableModelListener is not a good place to do validation, at that point in time the change already happened (the model notifies its listeners of the fact)
- as a consequence, whatever validation (verify) method hook you choose, never-ever talk back to the model, you'll end up in an infinite loop (as you have seen)
- application-provided CellEditorListeners are rather useless because a) there's no guarantee about sequence of notification (JTable might or not have already updated the model) b) the life-cylce of an editor is ill-defined
After all those (incomplete, unfortunately ;-) no-nos, a little hope: best bet is to implement a custom CellEditor which does the validation in stopCellCellEditing: if the new value isn't valid, return false and optionally provide a visual error feedback. Have a look at JTable.GenericEditor to get an idea of how that might be done
What worked for me (tip 'o the hat to kleopatra):
private class CellEditor extends DefaultCellEditor {
InputVerifier verifier = null;
public CellEditor(InputVerifier verifier) {
super(new JTextField());
this.verifier = verifier;
}
@Override
public boolean stopCellEditing() {
return verifier.verify(editorComponent) && super.stopCellEditing();
}
}
// ...
private class PortVerifier extends InputVerifier {
@Override
public boolean verify(JComponent input) {
boolean verified = false;
String text = ((JTextField) input).getText();
try {
int port = Integer.valueOf(text);
if ((0 < port) && (port <= 65535)) {
input.setBackground(Color.WHITE);
verified = true;
} else {
input.setBackground(Color.RED);
}
} catch (NumberFormatException e) {
input.setBackground(Color.RED);
}
return verified;
}
}
// ...
table.getColumn("Port").setCellEditor(new CellEditor(new PortVerifier()));