Java Swing JComboBox Tips

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

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.