JTable Integer Cell Editor with null values

836 Views Asked by At

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;
        }
    }

}

1

There are 1 best solutions below

0
Bro Emilio On

Finally, I found where I had to make a change. I'm enclosing the updated code.

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(fTextField.getText().isEmpty()) {
                            fTextField.setValue(null);
                             fTextField.postActionEvent();
                            }    else 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 revet 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;
        }
    }

}