A thing about Swing

The default behavior for rendering an object in a JComboBox is to call the toString() method of that object. If you don’t have a toString() defined, the JComboBox shows an object ID. So, the first try at using a JComboBox is to implement the toString() method in all your listable objects.

When in a development environment where you have to use other people’s objects, they might have other uses for toString() and that might not be available to you. So, the next try is to use custom renderers for all your listable objects. This is nice because it gives you complete control over how something is rendered in a JComboBox. A custom renderer returns a Component, usually a JLabel, though it could be made to return checkboxes and other components. One surprise is that once you start using a Renderer, all the usual behavior of a JComboBox (a blue box around the item you want, for example ), disappears. The first time you try it, you might find that the item you selected from your JComboBox becomes invisible.
There does not seem to be a reference to this, either in the Java API or in my Swing book, but setOpaque() must be set to true in your renderer for the JLabel be visible. The renderer does not assume that you would want to actually view the JLabel you requested. You also write your own behavior for what the JLabel does when you select it, meaning set the background to blue as follows:

if (isSelected) {
setBackground(Color.blue)
setForeground(Color.white);
} else {
setBackground(Color.white);
setForeground(Color.black);
}

Using custom renderers is explained here, but they don’t come out and tell you that part about setOpaque.

Related Posts

No related posts.

About Tim

Minneapolis Blogger
This entry was posted in swing. Bookmark the permalink.

One Response to A thing about Swing

  1. Brian Cole says:

    Something else that isn’t document very well (or even at all) is that your renderer may have to override setForeground() if you want the combo box to look right when it is disabled.

    This probably didn’t hit you, since you imply that
    the component returned by your renderer’s getListCellRendererComponent() is a JLabel. But if it were, say, a JPanel containing multiple JLabels, then you would have to override setForeground() in addition to makeing sure the JPanel is opaque.