Hi Pavel,

I start here a new thread for the "get/setSelectedItem(Object) methods of 
JComboBox and 
ComboBoxModel" discussion.

After further analysis of the code and your sample application I think we can 
and should generify 
the get/setSelectedItem(Object) methods of JComboBox and ComboBoxModel.

Yes, the Javadoc says that JComboBox/ ComboBoxModel supports selected values 
not managed by the 
underlying list model. But this does not prohibit to optionally limit the type 
by using generics und 
thus to increase type safety. 

If you need to allow other types from editor than the ones in the list model, 
you still can use:
JComboBox<Object> (or JComboBox, but this is not recommended)

So there should be no backward compatibility problem.

When using a JComboBox, usually you are interested in the selected value and 
since you want to do 
something with it you expect it to have some specific type. So if we generify 
the 
get/setSelectedItem(Object), you can profit from that in most cases.

Even in cases where you have an initial text in an editable combo box you can 
profit from that, if 
you use a "null" value as the selected value, which according to the API is 
used for "no selection", 
and a custom editor for rendering that null value. (see attachement; I used 
your sample application 
as a base; delete the text to set the selected value to null again).

-Florian
 



package combotest;

import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.lang.reflect.Method;

public class ComboTest {

    private static void createGui() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JComboBox cb = new JComboBox(new Integer[]{1, 2, 3});
        cb.setEditable(true);
        cb.setEditor(new IntegerComboBoxEditor());
        cb.setSelectedItem(null);
        frame.add(cb);

        cb.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (cb.getSelectedItem() == null) {
                    System.out.println("cb.getSelectedItem() = null");
                } else {
                    System.out.println("cb.getSelectedItem() = " + cb.
                            getSelectedItem().getClass() + ", " +
                            cb.getSelectedItem());
                }
            }
        });

        frame.setSize(400, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {

            public void run() {
                ComboTest.createGui();
            }
        });
    }

    private static class IntegerComboBoxEditor implements ComboBoxEditor {

        protected JTextField editor;
        private Object oldValue;

        public IntegerComboBoxEditor() {
            editor = new JTextField("", 25);
            editor.addFocusListener(new FocusAdapter() {

                @Override
                public void focusGained(FocusEvent e) {
                    editor.selectAll();
                }
            });
        }

        public Component getEditorComponent() {
            return editor;
        }

        /**
         * Sets the item that should be edited.
         *
         * @param anObject the displayed value of the editor
         */
        public void setItem(Object anObject) {
            if (anObject != null) {
                editor.setText(anObject.toString());
            } else {
                editor.setText("Select or enter a value");
            }
            oldValue = anObject;
        }

        public Object getItem() {
            String newValue = editor.getText();

            if (!newValue.equals("")) {
                if (oldValue != null && newValue.equals(oldValue.toString())) {
                    return oldValue;
                } else {
                    try {
                        return Integer.valueOf(newValue);
                    } catch (NumberFormatException e) {
                        setItem(oldValue);
                        return oldValue;
                    }
                }
            }
            setItem(null);
            return null;
        }

        public void selectAll() {
            editor.selectAll();
            editor.requestFocus();
        }

        public void addActionListener(ActionListener l) {
            editor.addActionListener(l);
        }

        public void removeActionListener(ActionListener l) {
            editor.removeActionListener(l);
        }
    }
}

Reply via email to