Java Tips Weblog

  • Blog Stats

    • 2,572,330 hits
  • Categories

  • Archives

Combo Box With Custom Renderer

Posted by Rob Camick on November 17, 2013

There may be times when you have a custom Object that you want to add to a JComboBox. Adding the Object to the ComboBoxModel is no problem, however getting the appropriate text to display in the combo box can be a problem. This is because the default renderer for the combo box will simply invoke the toString() method of the Object added to the combo box. Rarely will the toString() value be the text that you actually want displayed in the combo box. To solve this problem, the standard response you will find in the forums is to create a custom renderer.

Lets assume you have a Foo object that contains two properties (Id, Description). The “Id” will be used for further application processing and the “Description” will be displayed in the combo box. To view the Foo objects added to the combo box the custom renderer would look something like this:

class FooRenderer extends BasicComboBoxRenderer
{
	public Component getListCellRendererComponent(
		JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
	{
		super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

		if (value instanceof Foo)
		{
			Foo foo = (Foo)value;
			setText( foo.getDescription() );
		}

		return this;
	}
}

Unfortunately, this advice, which does solve the rendering problem, is only half of the solution because using a custom renderer will break default functionality of the combo box.

When using a GUI, the user should be able to use the mouse or the keyboard for any given interaction with a Swing component. Generally, most users will tend to use the mouse. However, advanced users will prefer to use the keyboard because it is often faster, especially in terms of data entry on a form. When using the keyboard with a combo box the user is able to enter the first character of the item to be selected in the combo box. The same character can be entered again to go to the next item starting with that character. Or, you can start typing the entire text of the item to be selected until a unique match is found.

This search functionality of the combo box is implemented by its KeySelectionManager. The default search implementation simply uses the toString() method of each Object as it does its search. When using a custom renderer we now have a problem because the rendered text does not match the toString() text so the search functionality is broken.

My solution to this problem is the KeySelectionRenderer. The KeySelectionRenderer class will be used as the renderer and the KeySelectionManager for the combo box. To use this class you must extend KeySelectionRenderer and implement the getDisplayValue(Object value) method. This method will simply return a text string based on the data from your custom Object that can be used by both the renderer and the KeySelectionManager.

To use the KeySelectionRenderer class with your combo box the code could be something like:

//  Create a combo box and add a few custom Foo objects

JComboBox fooComboBox = new JComboBox();
fooComboBox.addItem( new Foo(...) );
fooComboBox.addItem( new Foo(...) );
fooComboBox.addItem( new Foo(...) );

//  Use the KeySelectionRenderer to determine which property from the Foo object to display in the combo box

KeySelectionRenderer renderer = new KeySelectionRenderer(fooComboBox)
{
	@Override
	public String getDisplayValue(Object value)
	{
		Foo foo = (Foo)value;
		return foo.getDescription();
	}
};

When you create the KeySelectionRenderer it will automatically install itself as the custom renderer and KeySelectionManager for the specified combo box. Of course the display value could also be a combination of multiple properties from the Foo object.

Your combo box will likely use an ActionListener (or ItemListener) to do some type of processing when an item is selected. You have access to the entire Foo object with code like:

fooComboBox.addActionListener( new ActionListener()
{
	public void actionPerformed(ActionEvent e)
	{
      		JComboBox comboBox = (JComboBox)e.getSource();
      		Foo foo = (Foo)comboBox.getSelectedItem();
	}
});

So the next time you need a custom renderer for you combo box, maybe the KeySelectionRenderer can help you avoid breaking the default search functionality of a combo box.

Another option is to use the JXComboBox from the SwingX project which will support all this functionality and more. The JXComboxBox gives you far more flexibility when it comes to rendering.

Whatever you decide just remember that the search functionality of the combo box should not be ignored just because you are using a custom renderer.

Get The Code

KeySelectionRenderer.java

See Also

Combo Box With Hidden Data

Related Reading

Java API: JComboBox.KeySelectionManager

Leave a comment