Here's another jTable problem concerning edits on FocusLost. I want to enforce a strict policy of the focus not beeing able to leave a table cell unless the entered value is validated.
The table has a custom cell editor based on JFormattedTextField (excerpt):
class ThrowCellEditor extends AbstractCellEditor implements TableCellEditor {
private final ThrowTable table;
private JFormattedTextField jEditor;
public ThrowCellEditor(ThrowTable tb) {
table = tb;
jEditor = LDecor.getIntegerEditor();
jEditor.getInputMap().put(KeyStroke.getKeyStroke(
KeyEvent.VK_ENTER, 0),
"check");
jEditor.getActionMap().put("check", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
}
@Override
public boolean stopCellEditing() {
boolean hasStopped = false;
int ix = table.getEditingColumn();
if (((IntegerEditor)jEditor).testFormat()) {
return super.stopCellEditing();
}
return false;
}
}
getIntegerEditor() instantiates this class:
public class IntegerEditor extends JFormattedTextField {
public IntegerEditor() {
super();
//...FormatterFactory setup
setFormatterFactory(factory);
setFocusLostBehavior(JFormattedTextField.PERSIST);
}
public boolean testFormat() {
if (isEditValid()) {
try { commitEdit(); }
catch (ParseException exc) { }
} else {
//...show some Message
}
return true;
}
}
This takes care of catching parsing errors and averting the focus from susequently leaving the cell. Only, it just works when the focus tries to move inside the table. If the user clicks outside the table when a value is faulty, the error message issued by
testFormat() is shown, focus leaves the table and the cell returns to the old value in the renderer.
I tried two approaches to remedy this. First, using a FocusLost listener on the table basically reacts too late, since the original cell editor is already discarded. Thus an InputVerifier acting on the table seemed to be a good idea:
public ThrowTable() {
setModel(new ThrowTableModel());
setDefaultEditor(Integer.class, new ThrowCellEditor(this));
putClientProperty("terminateEditOnFocusLost", true);
setInputVerifier(new InputVerifier() {
//this never seems to be called
public boolean verify(JComponent input) {
JTable tb = (JTable)input;
JFormattedTextField ftf = (JFormattedTextField)tb.getEditorComponent();
return ftf.isEditValid();
}
});
setDefaultRenderer(Integer.class, new ThrowCellRenderer());
}
It just doesn't react.
Has anyone an idea?