Editing non-String values in JComboBox

53 Views Asked by At

I have a JComboBox which displays items which are not Strings, although they do have a toString() method and can be displayed as Strings.

I declare it as:

public class AddressCombo extends JComboBox<Address> {
    public AddressCombo(ComboBoxModel<Address> model) {
        super(model);
        setEditable(true);
    }

    public AddressCombo(Address... addresses) {
        this(new DefaultComboBoxModel<Address>(addresses));
    }
    
    // Other stuff snipped
}

This works fine when the JComboBox is not editable, but If I make it editable then the selected item becomes a java.lang.String when edited which is not what we want! In addition the String might not represent a valid value at all (we have a parser that can detect this).

What is the best way to set up a JComboBox so that:

  1. It manages items of a custom (POJO) type
  2. It is editable
  3. When the user edits the field, the user's input can be parsed with a custom parser to see if it is the correct type
  4. If the input doesn't parse, it can either be corrected or a default value used
  5. The selected item will therefore always be of the correct class, not a Java String
1

There are 1 best solutions below

0
mikera On

I found that the following solution worked:

  • Create a subclass of java.text.Format to encapsulate the formatting / parsing code
  • Create a custom subclass of BasicComboBoxEditor to use the formatter with a JFormattedTextField
  • Set the editor on the JComboBox sublass to use the above

Code for those interested:

public class AddressCombo extends JComboBox<Address> {
    
    private class AddressEditor extends BasicComboBoxEditor {   
        @Override 
        public Object getItem() {
            try {
                return AddressFormat.INSTANCE.parseObject(editor.getText());
            } catch (Exception e) {
                return null;
            }
        }
        
        @Override
        protected JFormattedTextField createEditorComponent() {
            JFormattedTextField fld= new JFormattedTextField(AddressFormat.INSTANCE);
            fld.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); 
            return fld;
        }
    }

    public AddressCombo(ComboBoxModel<Address> model) {
        super(model);
        setEditor(new AddressEditor());
        setEditable(true);
    }

    public AddressCombo() {
        this(new DefaultComboBoxModel<Address>());
    }
    
    public AddressCombo(Address... addresses) {
        this(new DefaultComboBoxModel<Address>(addresses));
    }

    // Irrelevant stuff snipped
}