JComboBox and Using an Anonymous Inner Class for Event Handling
A combo box (sometimes called a drop-down list) provides a list of items (Fig. 11.22) from which the user can make a single selection. Combo boxes are implemented with class JComboBox, which extends class JComponent. JComboBoxes generate ItemEvents like JCheckBoxes and JRadioButtons. This example also demonstrates a special form of inner class that is used frequently in event handling.
The application of Fig. 11.20 and Fig. 11.21 uses a JComboBox to provide a list of four image file names from which the user can select one image to display. When the user selects a name, the application displays the corresponding image as an Icon on a JLabel. Class ComboBoxTest (Fig. 11.21) contains the main method that executes this application. The screen captures for this application show the JComboBox list after the selection was made to illustrate which image file name was selected.
Figure 11.21. JComboBox that displays a list of image names.
(This item is displayed on page 544 in the print version)
1 // Fig. 11.21: ComboBoxFrame.java 2 // Using a JComboBox to select an image to display. 3 import java.awt.FlowLayout; 4 import java.awt.event.ItemListener; 5 import java.awt.event.ItemEvent; 6 import javax.swing.JFrame; 7 import javax.swing.JLabel; 8 import javax.swing.JComboBox; 9 import javax.swing.Icon; 10 import javax.swing.ImageIcon; 11 12 public class ComboBoxFrame extends JFrame 13 { 14 private JComboBox imagesJComboBox; // combobox to hold names of icons 15 private JLabel label; // label to display selected icon 16 17 private String names[] = 18 { "bug1.gif", "bug2.gif", "travelbug.gif", "buganim.gif" }; 19 private Icon icons[] = { 20 new ImageIcon( getClass().getResource( names[ 0 ] ) ), 21 new ImageIcon( getClass().getResource( names[ 1 ] ) ), 22 new ImageIcon( getClass().getResource( names[ 2 ] ) ), 23 new ImageIcon( getClass().getResource( names[ 3 ] ) ) }; 24 25 // ComboBoxFrame constructor adds JComboBox to JFrame 26 public ComboBoxFrame() 27 { 28 super( "Testing JComboBox" ); 29 setLayout( new FlowLayout() ); // set frame layout 30 31 imagesJComboBox = new JComboBox( names ); // set up JComboBox 32 imagesJComboBox.setMaximumRowCount( 3 ); // display three rows 33 34 imagesJComboBox.addItemListener( 35 new ItemListener() // anonymous inner class 36 { 37 // handle JComboBox event 38 public void itemStateChanged( ItemEvent event ) 39 { 40 // determine whether check box selected 41 if ( event.getStateChange() == ItemEvent.SELECTED ) 42 label.setIcon( icons[ 43 imagesJComboBox.getSelectedIndex() ] ); 44 } // end method itemStateChanged 45 } // end anonymous inner class 46 ); // end call to addItemListener 47 48 add( imagesJComboBox ); // add combobox to JFrame 49 label = new JLabel( icons[ 0 ] ); // display first icon 50 add( label ); // add label to JFrame 51 } // end ComboBoxFrame constructor 52 } // end class ComboBoxFrame |
Figure 11.22. Test class for ComboBoxFrame.
(This item is displayed on page 545 in the print version)
1 // Fig. 11.22: ComboBoxTest.java 2 // Testing ComboBoxFrame. 3 import javax.swing.JFrame; 4 5 public class ComboBoxTest 6 { 7 public static void main( String args[] ) 8 { 9 ComboBoxFrame comboBoxFrame = new ComboBoxFrame(); 10 comboBoxFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 11 comboBoxFrame.setSize( 350, 150 ); // set frame size 12 comboBoxFrame.setVisible( true ); // display frame 13 } // end main 14 } // end class ComboBoxTest
|
Lines 1923 (Fig. 11.20) declare and initialize array icons with four new ImageIcon objects. String array names (lines 1718) contains the names of the four image files that are stored in the same directory as the application.
At line 31, the constructor creates a JComboBox object, using the Strings in array names as the elements in the list. Each item in the list has an index. The first item is added at index 0, the next at index 1 and so forth. The first item added to a JComboBox appears as the currently selected item when the JComboBox is displayed. Other items are selected by clicking the JComboBox, which expands into a list from which the user can make a selection.
Line 32 uses JComboBox method setMaximumRowCount to set the maximum number of elements that are displayed when the user clicks the JComboBox. If there are additional items, the JComboBox provides a scrollbar (see the first screen capture) that allows the user to scroll through all the elements in the list. The user can click the scroll arrows at the top and bottom of the scrollbar to move up and down through the list one element at a time, or else drag the scroll box in the middle of the scrollbar up and down. To drag the scroll box, position the mouse cursor on it, hold the mouse button down and move the mouse.
Look-and-Feel Observation 11.11
Set the maximum row count for a JComboBox to a number of rows that prevents the list from expanding outside the bounds of the window in which it is used. This configuration will ensure that the list displays correctly when it is expanded by the user. |
Line 48 attaches the JComboBox to the ComboBoxFrame's FlowLayout (set in line 29). Line 49 creates the JLabel that is used to display each ImageIcon and initializes it with the first ImageIcon in array icons. Line 50 attaches the JLabel to the ComboBoxFrame's FlowLayout.
Using an Anonymous Inner Class for Event Handling
Lines 3446 are one statement that declares the event listener's class, creates an object of that class and registers that object as the listener for imagesJComboBox's ItemEvents. In this example, the event-listener object is an instance of an anonymous inner classa special form of inner class that is declared without a name and typically appears inside a method declaration. As with other inner classes, an anonymous inner class can access its top-level class's members. However, an anonymous inner class has limited access to the local variables of the method in which the anonymous inner class is declared. Since an anonymous inner class has no name, one object of the anonymous inner class must be created at the point where the class is declared.
Software Engineering Observation 11.5
An anonymous inner class declared in a method can access the instance variables and methods of the top-level class object that declared it, as well as the method's final local variables, but cannot access the method's non-final variables. |
Lines 3446 are a call to imagesJComboBox's addItemListener method. The argument to this method must be an object that is an ItemListener (i.e., any object of a class that implements ItemListener). Lines 3545 are a class-instance creation expression that declares an anonymous inner class and creates one object of that class. A reference to that object is then passed as the argument to addItemListener. The syntax ItemListener() after new begins the declaration of an anonymous inner class that implements interface ItemListener. This is similar to beginning a class declaration with
public class MyHandler implements ItemListener
The parentheses after ItemListener indicate a call to the default constructor of the anonymous inner class.
The opening left brace ({) at 36 and the closing right brace (}) at line 45 delimit the body of the anonymous inner class. Lines 3844 declare the ItemListener's itemStateChanged method. When the user makes a selection from imagesJComboBox, this method sets label's Icon. The Icon is selected from array icons by determining the index of the selected item in the JComboBox with method getSelectedIndex in line 43. Note that for each item selected from a JComboBox, another item is first deselectedso two ItemEvents occur when an item is selected. We wish to display only the icon for the item the user just selected. For this reason, line 41 determines whether ItemEvent method getStateChange returns ItemEvent.SELECTED. If so, lines 4243 set label's icon.
Software Engineering Observation 11.6
Like any other class, when an anonymous inner class implements an interface, the class must implement every method in the interface. |
The syntax shown in lines 3545 for creating an event handler with an anonymous inner class is similar to the code that would be generated by a Java integrated development environment (IDE). Typically, an IDE enables the programmer to design a GUI visually, then the IDE generates code that implements the GUI. The programmer simply inserts statements in the event-handling methods that declare how to handle each event.