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