Tải bản đầy đủ - 0 (trang)
Chapter 7. Lists, Combo Boxes, and Spinners

Chapter 7. Lists, Combo Boxes, and Spinners

Tải bản đầy đủ - 0trang

This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



I l@ve RuBoard



7.1 Lists

A list is a graphical component that presents the user with choices. Lists typically display several items at a time, allowing the

user to make either a single selection or multiple selections. In the event that the inventory of the list exceeds the space

available to the component, the list is often coupled with a scrollpane to allow navigation through the entire set of choices.

The Swing JList component allows elements to be any Java class capable of being rendered—which is to say anything at all

because you can supply your own renderer. This offers a wide range of flexibility; list components can be as simple or as

complex as the programmer's needs dictate.

Let's get our feet wet with a simple list. The following example uses the Swing list class, JList, to create a single-selection list

composed only of strings. Figure 7-1 shows the result.



Figure 7-1. A simple Swing list



// SimpleList.java

//

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class SimpleList extends JPanel {

String label[] = { "Zero","One","Two","Three","Four","Five","Six",

"Seven","Eight","Nine","Ten","Eleven" };

JList list;

public SimpleList( ) {

this.setLayout(new BorderLayout( ));

list = new JList(label);

JScrollPane pane = new JScrollPane(list);

JButton button = new JButton("Print");

button.addActionListener(new PrintListener( ));



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks

.



add(pane, BorderLayout.CENTER);

add(button, BorderLayout.SOUTH);

}

public static void main(String s[]) {

JFrame frame = new JFrame("Simple List Example");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setContentPane(new SimpleList( ));

frame.setSize(250, 200);

frame.setVisible(true);

}

// An inner class to respond to clicks of the Print button

class PrintListener implements ActionListener {

public void actionPerformed(ActionEvent e) {

int selected[] = list.getSelectedIndices( );

System.out.println("Selected Elements: ");

for (int i=0; i < selected.length; i++) {

String element =

(String)list.getModel( ).getElementAt(selected[i]);

System.out.println(" " + element);

}

}

}

}

Take a close look at the source. The first thing you might notice is that we embedded the Swing list inside the viewport of a

scrollpane object. The Swing JList class itself does not support scrolling through its data. Instead, it hands off the responsibility

to the JScrollPane class. This is a significant design change from its predecessor,java.awt.List, which automatically managed

a scrollbar for you. However, making a list the view of a scrollpane object fits better into the overall modular philosophy of

Swing. The clear separation of function allows developers to reuse a customized scrollbar (or scrollpane) with their own lists

instead of simply accepting a default provided with the list component. It also enables autoscrolling support, so you can drag the

mouse above or below the list, and its contents scroll automatically.

Try selecting multiple numbers (you can do this in most L&Fs by holding down the Shift key while clicking). Note that by using

Shift you can select only one range, or continuous set of numbers, at a time. If you select a number beyond the currentselection

range, the range is extended to cover everything in between. The first number selected (i.e., the one you didn't have to hold

Shift down for) becomes the initial endpoint for the range. This endpoint is called the anchor . The most recent selection (which

is outlined) forms the second endpoint. This element is called the lead . Together, the anchor and the lead form a range of

selections in the list, as shown in Figure 7-2.



Figure 7-2. The anchor and lead positions in a list selection



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks

.



When the user presses the button, an actionPerformed( ) method is called. This method reports all the items that are

currently selected in the list:



Selected Elements:

Four

Five

Six

Seven

Eight

There is also a way to make discontiguous selections (so you could select Four, Six, and Eight through Ten, for example). This

is done by holding down a different modifier key: on Unix and Windows this is typically theControl key while on the Macintosh

the Command (Apple) key is used. As usual, these differences are managed by the L&F. Since 1.3, the default behavior for a

list is to support both ranges and discontiguous selections. Prior versions allowed only a single range. All versions let you

override the default.

If you are using SDK 1.4 or later, you can also select elements in the list by typing the first characters in their label.



7.1.1 Anatomy of a Swing List

Now that we've seen the basics, let's take a closer look at JList . Figure 7-3 shows a high-level class diagram for Swing's list

classes. In particular, note the three interfaces in the middle.



Figure 7-3. Swing list class diagram



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks

.



Each list component consists of three parts, as shown in Figure 7-4. The first of the three parts is the elements that comprise the

list, called the list data . As you might guess, the list data is assigned to a model — an object implementing the

ListModel

interface represents the list data. By default, JList uses the DefaultListModel class, an implementation of ListModel that

stores a collection of data objects in a Vector. If you want a model more specific to your needs, the most convenient way to do

it is to extend the AbstractListModel class and add your specific functionality to the basic housekeeping it provides.



Figure 7-4. The three parts of a Swing list



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



The second element is a model as well; however, this one represents the user's selections. The model interface for selection

data is the ListSelectionModel . Like the list data model, it also has a standard implementation:DefaultListSelectionModel

. With the defaultJList, for example, you can select several ranges simultaneously. However, you can also program the

DefaultListSelectionModel to allow only one element to be selected at a given time.

The final piece is called a cell renderer



. A cell renderer defines how each cell displays its data in the list, including when the



cell is selected. Why an entire class for rendering list elements? As we mentioned previously, list data is not constrained to

strings. Icons and animations can be displayed in place of or next to descriptive text. In many Swing components, a cell

renderer is a common way to render complex data, or any data in a way that's specific to your application. If you write one

carefully, it can be reused in several locations.



7.1.2 Where to Go from Here?

The following sections outline the various models and support classes that make up a Swing list. If you simply want to get to

know the Swing JList class, you can skip ahead toSection 7.5, where we create a graphical list of some O'Reilly Java books. On

the other hand, if you want to learn more about the data and selection models of the JList, then read on!

I l@ve RuBoard



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



I l@ve RuBoard



.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



7.2 Representing List Data

Swing uses one interface and two classes to maintain a model of the list elements. When programming with lists,

you often find that you can reuse these classes without modification. Occasionally, you may find it necessary to

extend or even rewrite these classes to provide special functionality. In either case, it's important to examine all three

in detail. Let's start with the easiest: ListModel .



7.2.1 The ListModel Interface

ListModel is a simple interface for accessing the data of the list. It has four methods: one method to retrieve data in

the list, one method to obtain the total size of the list, and two methods to register and unregister change listeners on

the list data. Note that the ListModel interface itself contains a method only for retrieving the list elements — not for

setting them. Methods that set list values are defined in classes that implement this interface.



7.2.1.1 Properties



The ListModel interface defines two properties, shown inTable 7-1. elementAt is an indexed property that lets you

retrieve individual objects from the list; size tells you the total number of elements.



Table 7-1. ListModel properties

Property



Data type



get



elementAti



Object



·



size



int



·



i



is



set



Default value



indexed



7.2.1.2 Events



The ListModel interface also contains the standardaddListDataListener( ) and removeListDataListener( )

event subscription methods. These methods accept listeners that notify when the contents of the list have changed. A



ListDataEvent should be generated when elements in the list are added, removed, or modified.

ListDataEvent and

the ListDataListener interface are discussed later in this chapter.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



public abstract void addListDataListener(ListDataListener l)

public abstract void removeListDataListener(ListDataListener l)

Add or remove a specific listener for ListDataEvent notifications.



7.2.2 The AbstractListModel Class

The AbstractListModel class is a skeletal framework to simplify the life of programmers who want to implement the



ListModel interface. It provides the requiredaddListDataListener( ) and removeListDataListener( ) event

registration methods. It also provides three protected methods that subclasses can use to fire ListDataEvent

objects. These methods are triggered when an addition, subtraction, or modification to the list data has taken place.

Note that a ListDataEvent is not the same as aPropertyChangeEvent, which is more general in nature.

(ListDataEvent is covered later in this chapter.)



7.2.2.1 Methods



protected void fireContentsChanged(Object source, int index1, int index2)

Called by subclasses to trigger a ListDataEvent, which indicates that a modification has occurred in the

list elements between index1 and index2. index2 can be less thanindex1. The source parameter

provides a reference to the ListModel that signaled the change.



protected void fireIntervalAdded(Object source, int index1, int index2)

Called by subclasses to trigger a ListDataEvent, which indicates that the list elements betweenindex1 and



index2 (inclusive) have been added to the list. Assuming thatindex2 is the greater index, the element

previously at index1 in the list is now elementindex2+1. All subsequent elements are shifted as well.

index2 can be less thanindex1. The source parameter provides a reference to theListModel that signaled

the change.



protected void fireIntervalRemoved(Object source, int index1, int index2)

Called by subclasses to trigger a ListDataEvent, which indicates to a listener that the list elements from



index1 to index2 have been removed from the list. Assuming thatindex2 is the larger index, the element

previously at index2+1 now becomes index1, and all greater elements are shifted down accordingly.

index2 can be less thanindex1. The source parameter provides a reference to theListModel that signaled

the change.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



Although the AbstractListModel class completes the event framework defined by the list model interface, it does

not implement the remaining two methods of the ListModel interface: getSize( ) and getElementAt( ). Instead, it

defines these as abstract (making the entire class abstract), leaving the actual implementation choices of the list

storage to a subclass, such as DefaultListModel. Providing an abstract class that takes care of the mundane tasks

required by an interface is characteristic of the useful Skeletal Implementation design pattern found throughout

[1]

Java's Collections classes.

[1]



For a detailed discussion of this approach and its benefits, see "Item 16: Prefer interfaces to

abstract classes" in Joshua Bloch's Effective Java Programming Language Guide

(Addison-Wesley).

SDK 1.3 introduced a method to get the list of registered event listeners:

public EventListener[] getListeners(Class listenerType)

You need to pass in the type of listener you're interested in, which is generally the



ListDataListener.class, and you need to cast the result to that specific type.

SDK 1.4 introduced a simpler way to do the same thing:

public ListDataListener[] getListDataListeners( )

Return an array of all the list data listeners that have been registered.



7.2.3 The DefaultListModel Class

Swing provides a default implementation of the ListModel interface called DefaultListModel . This class is based

on the java.util.Vector class, a resizable array of objects that has been around since the early days of Java (the

comments keep saying that there are plans to replace this with a more modern Collection-based implementation, but

it hasn't happened yet). A majority of the methods of the DefaultListModel class are identical to those ofVector,

with the added (and necessary) feature that those methods fire a ListDataEvent each time the vector changes.



DefaultListModel extends AbstractListModel to take advantage of its listener-list management features.



7.2.3.1 Properties



The DefaultListModel class has three properties, shown inTable 7-2. The size property indicates how many

elements are currently stored in the list. You can use thesetSize( ) method to alter the size of the list. If the new size

is larger than the previous size, the additional elements are populated with null references, and the method fires a



ListDataEvent describing the range that was added. If the new size is smaller, the list is truncated, and the method

fires a ListDataEvent describing the range that was removed.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



Table 7-2. DefaultListModel properties

Property



Data type



elementAti



Object



empty



boolean



size



int



i



get



is



·



set



Default value



·

·



·



true

·



0



indexed



The empty property is aboolean that indicates whether the list has no elements.elementAt is an indexed property

that you can use to access the list elements. If you set a new element using the setElementAt( ) method, the

method fires a ListDataEvent describing the element that was changed.



7.2.3.2 Constructor



public DefaultListModel( )

Create an empty vector to be used as the list model.



7.2.3.3 Methods



public void copyInto(Object anArray[])

Copy all of the objects in the list into the array anArray, which must be large enough to hold the contents of

the model.



public void trimToSize( )

Collapse the capacity of the list to match its current size, removing any empty storage.



public void ensureCapacity(int minCapacity)

Tell the list to make sure that its capacity is at least minCapacity .



public int capacity( )

Return the current capacity of the list. The capacity is the number of objects the list can hold without



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



reallocating for more space.



public int size( )

Return the number of elements currently contained in the list. It is equivalent to getSize( ) .



public Enumeration elements( )

Return an Enumeration that iterates over each of the elements in the list.



public boolean contains(Object elem)

Return an indication of whether the object elem is currently contained in the list.



public int indexOf(Object elem)

Return the first index at which the object elem can be found in the list, or-1 if the object is not contained in

the list.

public int indexOf(Object elem, int index)

Return the first index at which the object elem can be found in the list, beginning its search at the element

specified by index and moving forward through the list. The method returns-1 if the object is not contained in

the list at or beyond index.



public int lastIndexOf(Object elem)

Return the last index at which the object elem can be found in the list. The method returns-1 if the object is

not contained in the list.

public int lastIndexOf(Object elem, int index)

Return the last index at which the object elem can be found in the list, searching backwards from the

element specified by index to the front of the list. The method returns-1 if the object is not contained in the

list at or before index.



public Object elementAt(int index)

Return a reference to the object at the specified index. It is equivalent to getElementAt(index) .



public Object firstElement( )

Return a reference to the first object in the list.

public Object lastElement( )



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 7. Lists, Combo Boxes, and Spinners

Tải bản đầy đủ ngay(0 tr)

×