This post is a sequel to Java Swing Tips which formerly contained a shorter version of these tips concerning JComboBox. I decided to extract them into their own post as they got rather long, and the section on custom rendering was not quite correct. As before I’m using Oracle OpenJDK 10 on Windows 10 for testing, but all Oracle Java Documentation links refer to Java SE 8 as that is the target version of my projects.
Custom Rendering
JComboBox
allows custom rendering of its items much like JList
, as described in the corresponding Swing Tutorial. There is a subtle pitfall here. The standard technique, as demonstrated in the tutorial, always declares a class implementing ListCellRenderer
that also extends some JComponent
subclass and then returns this
in getListCellRendererComponent
. That works, but you might be tempted to shorten the renderer class declaration to a lambda expression as follows:
comboBox.setRenderer( (list, value, index, isSelected, cellHasFocus) -> { // build the component we want to show return component; });
Now the list items do show up when the drop-down arrow is clicked, but the fixed field containing the selected item (shown above the list and when the list is closed) will always be blank. Apparently JComboBox
has a subtle bug: while the list cell renderer is correctly called to render items, the fixed field shows the object implementing ListCellRenderer
rather than the object returned by getListCellRendererComponent
.
This bug won’t surface if you return this
, as in the standard technique. Using an anonymous lambda expression class triggers the bug since the implementing object and the returned object are now different (and the implementing object is not even a JComponent
).
Another tip on custom JComboBox
rendering (courtesy of Stack Overflow): if you’re having trouble with correct background colors try calling setOpaque(isSelected)
in your list cell renderer method. This fixed these issues for me.
Unbounded Maximum Height
With certain layout managers you may notice that the fixed field of a JComboBox
grows inordinately tall. This is another bug which according to Stack Overflow also affects JTextField
(not tested by me): the maximum height defaults to unbounded rather than the preferred height of the field. The Stack Overflow reply recommend subclassing JComboBox
but here’s a simple one-off fix:
comboBox.setMaximumSize(new Dimension( comboBox.getMaximumSize().width, comboBox.getPreferredSize().height));