![]() |
|||
![]() ![]() |
![]() |
![]()
|
![]() |
The ComboBoxModelThe data model employed by the JComboBox class is an instance of the ComboBoxModel. This interface extends the ListModel interface. This means that the methods described in the previous section for the ListModel class hold for the ComboBoxModel class as well. It also means that the same class of listener, ListDataListener, can be used for both models. The ComboBoxModel adds methods that support a selected item in the list. The selected item is the item shown at the top of the combo box and when the combo box is not expanded. The ComboBoxModel interface is shown here: public interface ComboBoxModel extends ListModel { /** * Set the selected item **/ void setSelectedItem(Object anItem); /** * Return the selected item **/ Object getSelectedItem(); } The first thing you may notice about the ComboBoxModel interface is the inconsistencies with the ListModel. The ComboBoxModel and the JComboBox class call members of the control items, while the ListModel and the JList class call the members elements. This type of inconsistency makes working with these two controls more difficult than it needs be. For example, a reference to a JComboBox instance calls the getItemAt method to query a member of the combo box, while a reference to the ComboBoxModel calls the getElementAt method to query the exact same member. The following code fragment demonstrates this inconsistency. If the ComboBoxTest program adds the following line after the creation of the JComboBox instance, both of the println statements print Banana. This is shown in Figure 10.8.
JComboBox combobox = new JComboBox( data ); ComboBoxModel comboBoxModel = combobox.getModel(); Object item3 = combobox.getItemAt( 3 ); Object element3 = comboBoxModel.getElementAt( 3 ); System.out.println( item: + item3 ); System.out.println( element: + element3 ); The less obvious question to ask about the ComboBoxModel is: Why is it needed? The only feature added by the ComboBoxModel is management of a selected item. However, in the previous section you saw the elegant solution of selection state management being delegated to the ListSelectionModel by the JList class. The JComboBox class could have used the exact same solution. If the name inconsistencies were resolved and the list selection model, in single selection mode, or better still a SingleSelectionModel instance, was used by both the JList and JComboBox classes, there would be no difference to the programmer in basic functionality between one control and the other. Sharing models between different views is a powerful aspect of the MVC architecture. Unfortunately, the JFC missed the mark with these two particular controls. JComboBox Class and Model InteractionThe default model used by instances of the JComboBox class is the DefaultComboBoxModel class. It extends the AbstractListModel class presented earlier in this chapter. When the selected item is changed, it fires a ContentsChanged event with both the start and end indexes set to 1. This obviously breaks the semantics of the contentsChanged method contained in the ListDataListener interface. For better or worse, this is what is done by the DefaultComboBoxModel class. The DefaultComboBoxModel class implements the MutableComboBoxModel interface, shown in Listing 10.12. This interface is an extension of the ComboBoxModel interface that adds methods to edit the elements in the combo box. The addElement method appends the given object to the model. The insertElementAt method allows an object to be placed at the given offset into the model. The removeElement method removes the given element from the model, and the removeElementAt method removes the object at the specified index from the model. Listing 10.12 The MutableComboBoxModel Interface public interface MutableComboBoxModel extends ComboBoxModel { /** * Adds an item to the end of the model. */ public void addElement( Object obj ); /** * Adds an item to the end of the model. */ public void removeElement( Object obj ); /** * Adds an item at a specific index */ public void insertElementAt( Object obj, int index ); /** * Removes an item at a specific index */ public void removeElementAt( int index ); }
The JComboBox class listens to the ComboBoxModel currently in use. When the selected item changes in the model, the combo box sends an ActionEvent to any ActionListeners of the instance. This allows clients of the JComboBox class to listen for action events from the combo box rather than selection change events from the model. However, caution must be taken here. If a ComboBoxModel other than the default model is used, the ActionEvent notification may break because the ComboBoxModel does not define an event for the selected item being changed. As mentioned in the previous paragraph, the DefaultComboBoxModel class overloads the semantics of the ContentsChanged event. However, different implementations of the ComboBoxModel interface may not behave the same way. If the JComboBox class does not receive the magic ContentsChanged event, the ActionEvent will not be fired from the JComboBox instance. This would not be a problem if the models clearly defined the event that should be fired when the selected item changes. This is another argument for using a ListSelectionModel, or the restricted single selection variant SingleSelectionModel, for combo boxes. The command string sent in an ActionEvent can be set and queried with the setActionCommand and getActionCommand methods. For some unknown reason, actionCommand is not a bound property in the JComboBox class.
|
![]() |
|