This is actually a good question about one of Swing's limitations (and has bugged me for a long time).
One would need a read-only combobox when... (wait for it)... the form is currently in read-only mode. Note that input from the user elswhere may flip the form into edit mode at a moment's notice, so switching JComponents (using a JLabel for instance) would not be visually desirable, IMO. Also note that a disabled combo does not convey the same information to a user as a read-only combo would:
setEnabled(false)
-> entirely grayed out; the component cannot be interacted with; whatever data may be shown is not relevant and cannot be selected for Copy/Paste.
setReadOnly(true)
-> text component of combo is not grayed out (but the arrow is); the component cannot be interacted with; whatever data may be shown is relevant and can be selected.
Justification for this is that Swing did implement this for JTextComponents in the form of setEditable(boolean)
. Thanks guys for that, but I also need it for JComboBox, JCheckbox, JRadioButton, etc. We had to roll our own versions for this missing API.
Another Swing gaffe (IHMO) is the inconsistent API. JTextComponent.setEditable(boolean)
enforces a read-only behavior, whereas JComboBox.setEditable(boolean)
does not.
Arrrgh!!!
So, to the problem. You gotta roll up your sleeves a bit. For an editable combo:
Get the combo's editor component via
combo.getEditor().getEditorComponent()
. It's a JTextField. Cast it, and callsetEditable(false)
. This gives you both the functionality and appearance you want for the text portion of the combo.Get the combo's arrow component by iterating over getComponents() of the combo. It's the only AbstractButton you'll find. Call
setEnabled(false)
. This is for appearance only.Find all of the default mouse listeners that came with the combo (which should be all of them if you didn't add any yourself) and remove them from both the combo and the arrow button.
Keep a reference to these listeners and the arrow button in case you want to switch it back to when read-only = false.
Or something like that. Your mileage may vary.
Cue kleopatra with an endorsement for SwingX, which probably has this functionality already built-in (I don't know that for sure, I'm just guessing).
Good luck.