I'm trying to create Custom Cell Editor which allows enter only Integer values between 0 and 5000. I found some code but the problem occur when I try to replace old value(not null) by empty String (I would like to put null value there). I get option dialog with Edit and Revert options all the time. I'm tried modify methods: getCellEditorValue() and stopCellEditing() but without success. I hope it will be readable code because it's my first post(I placed IntegerCellEditor as inner class to keep it in one file).
Could you help me?
Code I'm using:
public class IntegerCellEditorFrame extends JFrame{
private static final long serialVersionUID = 1L;
public IntegerCellEditorFrame() {
JTable table = new JTable(new DefaultTableModel(5,1));
table.getColumnModel().getColumn(0).setCellEditor(new IntegerCellEditor(0,5000));
setTitle("Test IntegerCellEditor");
setMinimumSize(new Dimension(300,200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(table);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
IntegerCellEditorFrame frame = new IntegerCellEditorFrame();
frame.setVisible(true);
});
}
class IntegerCellEditor extends DefaultCellEditor{
private static final long serialVersionUID = 1L;
JFormattedTextField fTextField;
NumberFormat integerFormat;
private Integer minimum, maximum;
private boolean DEBUG = false;
IntegerCellEditor(int min, int max) {
super(new JFormattedTextField());
fTextField = (JFormattedTextField)getComponent();
minimum = new Integer(min);
maximum = new Integer(max);
//Set up the editor for the integer cells.
integerFormat = NumberFormat.getIntegerInstance();
NumberFormatter intFormatter = new NumberFormatter(integerFormat);
intFormatter.setFormat(integerFormat);
intFormatter.setMinimum(minimum);
intFormatter.setMaximum(maximum);
fTextField.setFormatterFactory(new DefaultFormatterFactory(intFormatter));
fTextField.setValue(minimum);
fTextField.setFocusLostBehavior(JFormattedTextField.PERSIST);
fTextField.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),"check");
fTextField.getActionMap().put("check", new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if(!fTextField.isEditValid()) { //The text is invalid.
if(userSaysRevert()) { //reverted
fTextField.postActionEvent(); //inform the editor
}
} else try { //The text is valid,
fTextField.commitEdit(); //so use it.
fTextField.postActionEvent(); //stop editing
} catch (java.text.ParseException exc) { }
}
});
}
public Object getCellEditorValue() {
JFormattedTextField ftf = (JFormattedTextField)getComponent();
Object o = ftf.getValue();
if(o==null)
return null;
if (o instanceof Integer) {
return o;
} else if (o instanceof Number) {
return new Integer(((Number)o).intValue());
} else {
if (DEBUG) {
System.out.println("getCellEditorValue: o isn't a Number");
}
try {
return integerFormat.parseObject(o.toString());
} catch (ParseException exc) {
System.err.println("getCellEditorValue: can't parse o: " + o);
return null;
}
}
}
public boolean stopCellEditing() {
JFormattedTextField ftf = (JFormattedTextField)getComponent();
if (ftf.isEditValid()) {
try {
ftf.commitEdit();
} catch (java.text.ParseException exc) { }
} else { //text is invalid
if (!userSaysRevert()) { //user wants to edit
return false; //don't let the editor go away
}
}
return super.stopCellEditing();
}
protected boolean userSaysRevert() {
fTextField.selectAll();
Object[] options = {"Edit","Revert"};
int answer = JOptionPane.showOptionDialog(
SwingUtilities.getWindowAncestor(fTextField),
"Value should be between "
+ minimum + " and "
+ maximum + ".\n"
+ "You can edit current value "
+ "or revert last correct value.",
"Value out of range",
JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
options,
options[1]);
if (answer == 1) { //Revert!
fTextField.setValue(fTextField.getValue());
return true;
}
return false;
}
}
}
Finally, I found where I had to make a change. I'm enclosing the updated code.
}