The ListModel Interface
As you saw in the previous section, the JList class provides convenience methods for creating a list from a vector or array. However, you will often need to present data in a list that is contained in a data structure more complex than a simple array or vector. To do this, the class containing the data can implement the ListModel interface. Then the class can be used as the data model for a JList instance. Listing 10.5 shows this interface. As you can see, implementing the ListModel is very simple. The class must be able to return the size of the list, as well as an element at any given index in the range of 0 through one less than the size of the list. The class implementing the ListModel interface must also manage ListDataListener instances.
Listing 10.5 The ListModel Interface
public interface ListModel
{
/**
* Returns the length of the list.
*/
int getSize();
/**
* Returns the value at the specified index.
*/
Object getElementAt(int index);
/**
* Add a listener to the list thats notified each time a change
* to the data model occurs.
* @param l the ListDataListener
*/
void addListDataListener(ListDataListener l);
/**
* Remove a listener from the list thats notified each time a
* change to the data model occurs.
* @param l the ListDataListener
*/
void removeListDataListener(ListDataListener l);
}
The ListDataListener interface and ListDataEvent class are shown in Listing 10.6. They are implemented by classes that are interested in changes to a ListModel. The JList class implements ListDataListener to observe changes in its data model. It is the responsibility of the model to fire the appropriate event when the data contained in the model changes. For example, if the list grows or shrinks, the intervalAdded or intervalRemoved method of listeners must be called so they can update their view.
The ListDataEvent class contains the information about which items in the list have changed. The type of the event can be queried with the getType method. This method will return one of the three constants defined in the event. However, the type is somewhat redundant because an INTERVAL_ADDED type event is the parameter for the intervalAdded method, an INTERVAL_REMOVED type event is the parameter for the intervalRemoved method, and an INTERVAL_CHANGED type event is the parameter for the contentsChanged method. The two indices that are contained in the event, and returned from the getIndex0 and getIndex1 methods, define the range of items that are associated with the event. The range is inclusive of the values returned from the get methods.
Listing 10.6 The ListDataListener Interface
public interface ListDataListener extends EventListener {
/**
* Sent after the indices in the index0,index1
* interval have been inserted in the data model.
* The new interval includes both index0 and index1.
*/
void intervalAdded(ListDataEvent e);
/**
* Sent after the indices in the index0,index1 interval
* have been removed from the data model. The interval
* includes both index0 and index1.
*/
void intervalRemoved(ListDataEvent e);
/**
* Sent when the contents of the list have changed in a way
* thats too complex to characterize with the previous
* methods. Index0 and index1 bracket the change.
*/
void contentsChanged(ListDataEvent e);
}
public class ListDataEvent extends EventObject
{
public static final int CONTENTS_CHANGED = 0;
public static final int INTERVAL_ADDED = 1;
public static final int INTERVAL_REMOVED = 2;
private int type;
private int index0;
private int index1;
public int getType() { return type; }
public int getIndex0() { return index0; }
public int getIndex1() { return index1; }
public ListDataEvent(Object source,int type,int index0,int index1) {
super(source);
this.type = type;
this.index0 = index0;
this.index1 = index1;
}
}
|