A combo box uses a renderer to display each item in its menu.
If the combo box is uneditable,
it also uses the renderer to display the currently selected item.
An editable combo box, on the other hand,
uses an editor to display the selected item.
A renderer for a combo box must implement the
ListCellRenderer interface.
A combo box's editor must implement
ComboBoxEditor.
This section shows how to provide
a custom renderer for an uneditable combo box.
The default renderer knows how to render strings and icons.
If you put other objects in a combo box,
the default renderer calls the toString
method to provide a string to display.
You can customize the way a combo box renders itself
and its items
by implementing your own ListCellRenderer.
Here's a picture of an application
that uses a combo box with a custom renderer:
You can run CustomComboBoxDemo (
download JDK 6).
The full source code for this example is in
CustomComboBoxDemo.java.
To get the image files it requires,
consult the
example index.
The following statements from the example
create an instance of ComboBoxRenderer
(a custom class)
and set up the instance as the combo box's renderer:
JComboBox petList = new JComboBox(intArray);
. . .
ComboBoxRenderer renderer = new ComboBoxRenderer();
renderer.setPreferredSize(new Dimension(200, 130));
petList.setRenderer(renderer);
petList.setMaximumRowCount(3);
The last line sets the combo box's maximum row count,
which determines the number of items visible when
the menu is displayed.
If the number of items in the combo box is larger than
its maximum row count, the menu has a scroll bar.
The icons are pretty big for a menu,
so our code limits the number of rows to 3.
Here's the implementation of ComboBoxRenderer,
a renderer that puts an icon and text side-by-side:
class ComboBoxRenderer extends JLabel
implements ListCellRenderer {
. . .
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
/*
* This method finds the image and text corresponding
* to the selected value and returns the label, set up
* to display the text and image.
*/
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
//Get the selected index. (The index param isn't
//always valid, so just use the value.)
int selectedIndex = ((Integer)value).intValue();
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
//Set the icon and text. If icon was null, say so.
ImageIcon icon = images[selectedIndex];
String pet = petStrings[selectedIndex];
setIcon(icon);
if (icon != null) {
setText(pet);
setFont(list.getFont());
} else {
setUhOhText(pet + " (no image available)",
list.getFont());
}
return this;
}
. . .
}
As a ListCellRenderer,
ComboBoxRenderer implements a method
called getListCellRendererComponent,
which returns a component whose paintComponent
method is used to display the combo box and each of its items.
The easiest way to display an image and an icon
is to use a label.
So ComboBoxRenderer is a subclass of label
and returns itself.
The implementation of getListCellRendererComponent
configures the renderer to display the currently selected
icon and its description.
These arguments are passed to getListCellRendererComponent:
-
JList list —
a list object used behind the scenes
to display the items.
The example uses this object's colors
to set up foreground and background colors.
-
Object value —
the object to render.
An Integer in this example.
-
int index —
the index of the object to render.
-
boolean isSelected —
indicates whether the
object to render is selected.
Used by the example to determine which colors to use.
-
boolean cellHasFocus —
indicates whether the
object to render has the focus.
Note that combo boxes and lists
use the same type of renderer —
ListCellRenderer.
You can save yourself some time
by sharing renderers between
combo boxes and lists,
if it makes sense for your program.