How to Use Combo Boxes

 < Day Day Up > 

A JComboBox , [20] which lets the user choose one of several choices, can have two very different forms. The default form is the uneditable combo box, which features a button and a drop-down list of values. The second form is the editable combo box, which features a text field with a small button next to it. The user can type a value in the text field or click the button to display a drop-down list. Figure 7 shows what the two forms of combo box look like in the Java look and feel.

[20] JComboBox API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JComboBox.html.

Figure 7. (a) Uneditable combo box, before ( top ) and after the button is clicked; (b) editable combo box, before ( top ) and after the arrow button is clicked.

graphics/07fig07.gif

Combo boxes require little screen space, and their editable (text field) form is useful for letting the user quickly choose a value without limiting her to the displayed values. Other components that can display one-of-many choices are groups of radio buttons and lists. Groups of radio buttons are generally the easiest for users to understand, but combo boxes can be more appropriate when space is limited or more than a few choices are available. Lists aren't terribly attractive, but they're more appropriate than combo boxes when the number of items is large (say, more than 20) or when selecting multiple items might be valid.

Using an Uneditable Combo Box

The application shown in Figure 8 uses an uneditable combo box for choosing a pet picture.

Figure 8. The ComboBoxDemo application.

graphics/07fig08.jpg

Try This:

  1. graphics/cd_icon.gif

    Run ComboBoxDemo using Java Web Start or compile and run the source code your-self. [21]

    [21] To run ComboBoxDemo using Java Web Start, click the ComboBoxDemo link on the RunExamples/components.html page on the CD. You can find the source files here: JavaTutorial/uiswing/components/example-1dot4/index.html#ComboBoxDemo .

  2. Choose an animal name from the combo box to view its picture.

  3. graphics/cd_icon.gif

    Compare the operation and GUI of this program to one that uses radio buttons; run RadioButtonDemo . [22]

    [22] To run RadioButtonDemo using Java Web Start, click the RadioButtonDemo link on the RunExamples/components.html page on the CD. You can find the source files here: JavaTutorial/uiswing/components/example-1dot4/index.html#RadioButtonDemo .

The following code, taken from ComboBoxDemo.java , creates an uneditable combo box and sets it up:

 String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" }; //Create the combo box, select item at index 4. //Indices start at 0, so 4 specifies the pig. JComboBox petList = new JComboBox(petStrings); petList.setSelectedIndex(4); petList.addActionListener(this); 

This combo box contains an array of strings, but you could just as easily use icons instead. To put anything else into a combo box or to customize how the items in it look, you need to write a custom renderer. An editable combo box also needs a custom editor. See Providing a Custom Renderer (page 181) for information and an example.

The preceding code registers an action listener on the combo box. To see the action listener implementation and learn about other types of listeners supported by JComboBox , refer to Handling Events on a Combo Box (page 178).

No matter which constructor you use, a combo box uses a combo box model to contain and manage the items in its menu. When you initialize a combo box with an array or a vector, the combo box creates a default model object for you. As with other Swing components, you can customize a combo box in part by implementing a custom modelan object that implements the ComboBoxModel interface.

Note: Be careful when implementing a custom model for a combo box. The JComboBox methods that change the items in the combo box's menu, such as insertItemAt , work only if the data model implements the MutableComboBoxModel [23] interface (a subinterface of ComboBoxModel ). Refer to the API tables to see which methods are affected (page 184).

[23] MutableComboBoxModel API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/MutableComboBoxModel.html.

Something else to watch out foreven for uneditable combo boxesis ensuring that your custom model fires list data events when the combo box's data or state changes. Even immutable combo box models, whose data never changes, must fire a list data event (a CONTENTS_CHANGED event) when the selection changes. One way to get the list data event firing code for free is to make your combo box model a subclass of AbstractListModel .


Handling Events on a Combo Box

Here's the code from ComboBoxDemo.java that registers and implements an action listener on the combo box:

 public class ComboBoxDemo ... implements ActionListener {     . . .         petList.addActionListener(this) {     . . .     public void actionPerformed(ActionEvent e) {         JComboBox cb = (JComboBox)e.getSource();         String petName = (String)cb.getSelectedItem();         updateLabel(petName);     }     . . . } 

This action listener gets the newly selected item from the combo box, uses it to compute the name of an image file, and updates a label to display the image. The combo box fires an action event when the user selects an item from the combo box's menu. See How to Write an Action Listener (page 646) in Chapter 10 for general information about implementing action listeners.

Combo boxes also generate item events, which are fired when the selection state of any item changes. Only one item at a time can be selected in a combo box, so when the user makes a new selection the previously selected item becomes unselected . Thus, two item events are fired each time the user selects a different item from the menu. If the user chooses the same item, no item events are fired . Use addItemListener to register an item listener on a combo box. How to Write an Item Listener (page 674) in Chapter 10 gives general information about implementing item listeners.

Although JComboBox inherits methods to register listeners for low-level eventsfocus, key, and mouse events, for examplewe recommend that you don't listen for low-level events on a combo box. Here's why: A combo box is a compound component , comprising two or more other components. The combo box itself fires high-level events such as actions. Its subcomponents fire low-level events such as mouse, key, and focus events. The low-level events and the subcomponent that fires them are look-and-feel-dependent. To avoid writing look-and-feel-dependent code, you should listen only for high-level events on a compound component such as a combo box.

For information about events, including a discussion of high- and low-level events, see Chapter 5, Writing Event Listeners (page 107).

Using an Editable Combo Box

Figure 9 is a picture of a demo application that uses an editable combo box to enter a pattern with which to format dates.

Figure 9. ComboBoxDemo2 , an application that demonstrates the use of editable combo boxes.

graphics/07fig09.jpg

Try This:

  1. graphics/cd_icon.gif

    Run ComboBoxDemo2 using Java Web Start or compile and run the source code yourself. [24]

    [24] To run ComboBoxDemo2 using Java Web Start, click the ComboBoxDemo2 link on the RunExamples/components.html page on the CD. You can find the source files here: JavaTutorial/uiswing/components/example-1dot4/index.html#ComboBoxDemo2 .

  2. Enter a new pattern by choosing one from the combo box's menu. The program reformats the current date and time.

  3. Enter a new pattern by typing one in and pressing Enter. Again the program reformats the current date and time.

The following code, taken from ComboBoxDemo2.java , creates and sets up the combo box:

 String[] patternExamples = {          "dd MMMMM yyyy",          "dd.MM.yy",          "MM/dd/yy",          "yyyy.MM.dd G 'at' hh:mm:ss z",          "EEE, MMM d, ''yy",          "h:mm a",          "H:mm:ss:SSS",          "K:mm a,z",          "yyyy.MMMMM.dd GGG hh:mm aaa" }; . . . JComboBox patternList = new JComboBox(patternExamples);  patternList.setEditable(true);  patternList.addActionListener(this); 

It's very similar to the previous example, but warrants a few words of explanation. The bold line explicitly turns on editing to allow the user to type in values. This is necessary because, by default, a combo box is not editable. This particular example allows editing on the combo box because its menu doesn't provide all possible date-formatting patterns but just shortcuts to frequently used patterns.

An editable combo box fires an action event when the user chooses an item from the menu and when the user presses Enter. Note that the menu remains unchanged when the user enters a value into the combo box. If you want, you can easily write an action listener that adds a new item to the combo box's menu each time the user types in a unique value.

See The Java Tutorial's "Internationalization" trail to learn more about formatting dates and other types of data. [25]

[25] The "Internationalization" trail is available in The Java Tutorial on this book's CD and online at: http://java.sun.com/docs/books/tutorial/i18n/index.html.

Providing a Custom Renderer

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 [26] interface; a combo box's editor must implement ComboBoxEditor . [27] This section shows how to provide a custom renderer for an uneditable combo box.

[26] ListCellRenderer API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/ListCellRenderer.html.

[27] ComboBoxEditor API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/ComboBoxEditor.html.

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 .

Figure 10 is a picture of an application that uses a combo box with a custom renderer.

Figure 10. This application uses a combo box with a custom renderer.

graphics/07fig10.jpg

graphics/cd_icon.gif

You can run CustomComboBoxDemo using Java Web Start or compile and run the source code yourself. [28]

[28] To run CustomComboBoxDemo using Java Web Start, click the CustomComboBoxDemo link on the RunExamples/components.html page on the CD. You can find the source files here: JavaTutorial/uiswing/components/example-1dot4/index.html#CustomComboBoxDemo .

The following statements from the example create an instance of ComboBoxRenderer (a custom class) and set it up 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 three. Here's the implementation of ComboBox-Renderer , which 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. It's 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 [29] both use ListCellRenderer . You can save yourself some time by sharing renderers between combo boxes and lists if it makes sense for your program.

[29] See How to Use Lists (page 267).

The Combo Box API

Tables 10 and 11 list the commonly used JComboBox constructors and methods. Other methods you're most likely to invoke on a JComboBox object are those the object inherits from its superclasses, such as setPreferredSize . See The JComponent Class (page 53) in Chapter 3 for tables of commonly used inherited methods. You can also refer to the API documentation for JComboBox . [30]

[30] JComboBox API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JComboBox.html.

Table 10. Setting or Getting the Items in the Combo Box Menu

Method

Purpose

 JComboBox() JComboBox(ComboBoxModel) JComboBox(Object[]) JComboBox(Vector) 

Create a combo box with the specified items in its menu. A combo box created with the default constructor has no items in the menu initially. Each of the other constructors initializes the menu from its argument: a model object, an array of objects, or a Vector of objects.

 void addItem(Object) void insertItemAt(Object, int) 

Add or insert the specified object in the combo box menu. The insert method places the specified object at the specified index, thus inserting it before the object currently at that index. These methods require that the combo box data model be an instance of MutableComboBoxModel .

 Object getItemAt(int) Object getSelectedItem() 

Get an item from the combo box menu.

 void removeAllItems() void removeItemAt(int) void removeItem(Object) 

Remove one or more items from the combo box menu. These methods require that the combo box data model be an instance of MutableComboBoxModel .

int getItemCount()

Get the number of items in the combo box menu.

 void setModel(ComboBoxModel) ComboBoxModel getModel() 

Set or get the data model that provides the items in the combo box menu.

 void setAction(Action) Action getAction() 

Set or get the Action associated with the combo box. For further information, see How to Use Actions (page 513) in Chapter 9. Introduced in 1.3.

Table 11. Customizing the Combo Box's Operation

Method or Constructor

Purpose

void addActionListener(ActionListener)

Add an action listener to the combo box. The listener's actionPerformed method is called when the user selects an item from the combo box menu or, in an editable combo box, when the user presses Enter.

void addItemListener(ItemListener)

Add an item listener to the combo box. The listener's itemStateChanged method is called when the selection state of any combo box item changes.

 void setEditable(boolean) boolean isEditable() 

Set or get whether the user can type in the combo box.

 void setRenderer(ListCellRenderer) ListCellRenderer getRenderer() 

Set or get the object responsible for painting the selected item in the combo box. The renderer is used only when the combo box is uneditable. If the combo box is editable, the editor is used to paint the selected item instead.

 void setEditor(ComboBoxEditor) ComboBoxEditor getEditor() 

Set or get the object responsible for painting and editing the selected item in the combo box. The editor is used only when the combo box is editable. If the combo box is uneditable, the renderer is used to paint the selected item instead.

Examples That Use Combo Boxes

The following table shows examples that use JComboBox and where those examples are described.

Example

Where Described

Notes

ComboBoxDemo

This section

Uses an uneditable combo box.

ComboBoxDemo2

This section

Uses an editable combo box.

CustomComboBoxDemo

This section

Provides a custom renderer for a combo box.

LunarPhases

Example Five: LunarPhases (page 25)

Uses an uneditable combo box.

TableRenderDemo

How to Use Tables (page 388)

Shows how to use a combo box as a table cell editor.

 < Day Day Up > 


JFC Swing Tutorial, The. A Guide to Constructing GUIs
The JFC Swing Tutorial: A Guide to Constructing GUIs (2nd Edition)
ISBN: 0201914670
EAN: 2147483647
Year: 2004
Pages: 171

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net