The JFC Swing Tutorial: A Guide to Constructing GUIs (2nd Edition)

 < Day Day Up > 

A JList [82] presents the user with a group of items, displayed in one or more columns , to choose from. Lists can have many items, so they are often put in scroll panes.

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

In addition to lists, the following Swing components present multiple selectable items to the user: combo boxes, menus , tables, and groups of check boxes or radio buttons . To display hierarchical data, use a tree.

Figure 30 shows two GUIs that use lists. This section uses these examples as a basis for the discussions that follow.

Figure 30. Screenshots of ListDialog (used by ListDialogRunner ) and ListDemo .

Try This:

  1. Run ListDialogRunner and ListDemo using Java Web Start or compile and run the examples yourself. [83]

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

  2. To bring up the ListDialog , click the Pick a new name ... button in the window titled "Name That Baby." The resulting dialog is a ListDialog instance that's been customized to have the title "Name Chooser."

  3. In ListDemo , try adding (hiring) and removing (firing) a few items.

Initializing a List

Here's the code from ListDialog.java that creates and sets up its list:

list = new JList(data); //data has type Object[] list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); list.setLayoutOrientation(JList.HORIZONTAL_WRAP); list.setVisibleRowCount(-1); ... JScrollPane listScroller = new JScrollPane(list); listScroller.setPreferredSize(new Dimension(250, 80));

The code passes an array to the list's constructor. The array is filled with strings that were passed in from another object. In our example, the strings happen to be boys' names .

Other JList constructors let you initialize a list from a Vector or from an object that adheres to the ListModel [84] interface. If you initialize a list with an array or vector, the constructor implicitly creates a default list model. The default list model is immutableyou cannot add, remove, or replace items in the list. To create a list whose items can be changed individually, set the list's model to an instance of a mutable list model class, such as an instance of DefaultListModel . [85] You can set a list's model when you create the list or by calling the setModel method. See Adding Items to and Removing Items from a List (page 270) for an example.

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

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

The call to setSelectionMode specifies how many items the user can select and whether they must be contiguous. The next section tells you more about selection modes.

The call to setLayoutOrientation lets the list display its data in multiple columns. The value JList.HORIZONTAL_WRAP specifies that the list should display its items from left to right before wrapping to a new row. Another possible value is JList.VERTICAL_WRAP , which specifies that the data be displayed from top to bottom (as usual) before wrapping to a new column. The following figures show these two wrapping possibilities, together with the default, JList.VERTICAL .

In combination with the call to setLayoutOrientation , invoking the method setVisibleRowCount(-1) makes the list display the maximum number of items possible in the available space onscreen. Another common use of setVisibleRowCount is to specify to the lists's scroll pane how many rows the list prefers to display.

Selecting Items in a List

A list uses an instance of ListSelectionModel [86] to manage its selection. By default, a list selection model allows any combination of items to be selected at a time. You can specify a different selection mode by calling the setSelectionMode method on the list. For example, both ListDialog and ListDemo set the selection mode to SINGLE_SELECTION (a constant defined by ListSelectionModel ) so that only one item in the list can be selected. The following table describes the three list selection modes.

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

SINGLE_SELECTION

Only one item can be selected at a time. When the user selects an item, any previously selected item is deselected first.

SINGLE_INTERVAL_SELECTION

Multiple, contiguous items can be selected. When the user begins a new selection range, any previously selected items are deselected first.

MULTIPLE_INTERVAL_SELECTION

The default. Any combination of items can be selected. The user must explicitly deselect items.

No matter which selection mode your list uses, the list fires list selection events whenever the selection changes. You can process these events by adding a list selection listener [87] to the list with the addListSelectionListener method. A list selection listener must implement one method: valueChanged . Here's the valueChanged method for the listener in ListDemo :

[87] See How to Write a List Selection Listener (page 685).

public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting() == false) { if (list.getSelectedIndex() == -1){ //No selection, disable fire button. fireButton.setEnabled(false); } else { //Selection, enable the fire button. fireButton.setEnabled(true); } } }

Many list selection events can be generated from a single user action such as a mouse click. The getValueIsAdjusting method returns true if the user is still manipulating the selection. This particular program is interested only in the final result of the user's action, so the valueChanged method does something only if getValueIsAdjusting returns false .

Because the list is in single-selection mode, this code can use getSelectedIndex to get the index of the just-selected item. JList provides other methods for setting or getting the selection when the selection mode allows more than one item to be selected. If you want, you can listen for events on the list's list selection model rather than on the list itself. ListSelectionDemo [88] is an example that shows how to listen for list selection events on the list selection model and lets you change the selection mode of a list dynamically.

[88] ListSelectionDemo is featured in How to Write a List Selection Listener (page 685) in Chapter 10.

Adding Items to and Removing Items from a List

The ListDemo example that we showed previously features a list whose contents can change. Here's the ListDemo code that creates a mutable list model object, puts the initial items in it, and uses the list model to create a list:

listModel = new DefaultListModel(); listModel.addElement("Alison Huml"); listModel.addElement("Kathy Walrath"); listModel.addElement("Lisa Friendly"); listModel.addElement("Mary Campione"); listModel.addElement("Sharon Zakhour"); listModel.addElement("Alan Sommerer"); list = new JList(listModel);

This particular program uses an instance of DefaultListModel , a class provided by Swing. In spite of the class name, a list does not have a DefaultListModel unless your program explicitly makes it so. If DefaultListModel doesn't suit your needs, you can write a custom list model, which must adhere to the ListModel interface.

The following code snippet shows the actionPerformed method for the action listener registered on the Fire button. The bold line of code removes the selected item in the list. The remaining lines in the method disable the Fire button if the list is now empty, and make another selection if it's not.

public void actionPerformed(ActionEvent e) { int index = list.getSelectedIndex(); listModel.remove(index); int size = listModel.getSize(); if (size == 0) { //Nobody's left, disable firing. fireButton.setEnabled(false); } else { //Select an index. if (index == listModel.getSize()) { //removed item in last position index--; } list.setSelectedIndex(index); list.ensureIndexIsVisible(index); } }

Here's the actionPerformed method for the action listener shared by the Hire button and the text field:

public void actionPerformed(ActionEvent e) { String name = employeeName.getText(); //User didn't type in a unique name... if (name.equals("") alreadyInList(name)) { Toolkit.getDefaultToolkit().beep(); employeeName.requestFocusInWindow(); employeeName.selectAll(); return; } int index = list.getSelectedIndex(); //get selected index if (index == -1) { //no selection, so insert at beginning index = 0; } else { //add after the selected item index++; } listModel.insertElementAt(employeeName.getText(), index); //Reset the text field. employeeName.requestFocusInWindow(); employeeName.setText(""); //Select the new item and make it visible. list.setSelectedIndex(index); list.ensureIndexIsVisible(index); }

This bold line of code uses the list model's insertElementAt method to insert the new name after the current selection or, if no selection exists, at the beginning of the list. If you just want to add to the end of the list, you can use DefaultListModel 's addElement method instead.

Whenever items are added to, removed from, or modified in a list, the list model fires list data events. Refer to How to Write a List Data Listener (page 682) for information about listening for these events. That section contains an example that is similar to ListDemo but adds buttons that move items up or down in the list.

Writing a Custom Cell Renderer

A list uses an object called a cell renderer to display each of its items. The default cell renderer knows how to display strings and icons. If you want to put any other Object in a list or if you want to change the way the default renderer displays icons or strings, you can implement a custom cell renderer. Take these steps to provide a custom cell renderer for a list:

  • Write a class that implements the ListCellRenderer interface. [89]

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

  • Create an instance of your class and call the list's setCellRenderer method using the instance as an argument.

We don't provide an example of a list with a custom cell renderer, but we do have an example of a combo box with a custom rendererand combo boxes use the same type of renderer as lists. See the example described in Providing a Custom Renderer (page 181).

The List API

Tables 44 through 47 list the commonly used JList constructors and methods. Other methods you are most likely to invoke on a JList object are those such as setPreferredSize that its superclasses provide. See The JComponent API (page 55) for tables of commonly used inherited methods. Also refer to the JList API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JList.html.

Much of the operation of a list is managed by other objects. The items in the list are managed by a list model object, the selection is managed by a list selection model object, and most programs put a list in a scroll pane to handle scrolling. For the most part, you don't need to worry about the models because JList creates them as necessary and you interact with them implicitly with JList 's convenience methods.

Table 44. Initializing List Data

Method or Constructor

Purpose

JList(ListModel) JList(Object[]) JList(Vector) JList()

Create a list with the initial list items specified. The second and third constructors implicitly create an immutable ListModel ; you should not subsequently modify the passed-in array or Vector .

void setModel(ListModel) ListModel getModel()

Set or get the model that contains the contents of the list.

void setListData(Object[]) void setListData(Vector)

Set the items in the list. These methods implicitly create an immutable ListModel .

Table 45. Displaying the List

Method

Purpose

void setVisibleRowCount(int) int getVisibleRowCount()

Set or get how many rows of the list should be visible.

void setLayoutOrientation(int) int getLayoutOrientation()

Set or get the way list cells are laid out. The possible layout formats are specified by the JList -defined values VERTICAL (a single column of cells; the default), HORIZONTAL_WRAP ("newspaper" style with the content flowing horizontally then vertically), and VERTICAL_WRAP ("newspaper" style with the content flowing vertically then horizontally). Introduced in 1.4.

int getFirstVisibleIndex() int getLastVisibleIndex()

Get the index of the first or last visible item.

void ensureIndexIsVisible(int)

Scroll so that the specified index is visible within the viewport that this list is in.

Table 46. Managing the List's Selection

Method

Purpose

void addListSelectionListener( ListSelectionListener)

Register to receive notification of selection changes.

void setSelectedIndex(int) void setSelectedIndices(int[]) void setSelectedValue(Object, boolean) void setSelectionInterval(int, int)

Set the current selection as indicated. Use setSelectionMode to set what ranges of selections are acceptable. The boolean argument specifies whether the list should attempt to scroll itself so that the selected item is visible.

int getSelectedIndex() int getMinSelectionIndex() int getMaxSelectionIndex() int[] getSelectedIndices() Object getSelectedValue() Object[] getSelectedValues()

Get information about the current selection as indicated.

void setSelectionMode(int) int getSelectionMode()

Set or get the selection mode. Acceptable values are: SINGLE_SELECTION , SINGLE_INTERVAL_SELECTION , or MULTIPLE_INTERVAL_SELECTION (the default), which are defined in ListSelectionModel .

void clearSelection() boolean isSelectionEmpty()

Set or get whether any items are selected.

boolean isSelectedIndex(int)

Determine whether the specified index is selected.

Table 47. Managing List Data

Class or Method

Purpose

int getNextMatch( String, int, javax.swing.text.Position.Bias)

Given the starting index, search through the list for an item that starts with the specified string and return that index (or -1 if the string isn't found). The third argument, which specifies the search direction, can be either Position.Bias.Forward or Position. Bias.Backward . For example, if you have a 6-item list, getNextMatch("Matisse", 5, javax.swing.text.Position . Bias.Forward) searches for the string "Matisse" in the item at index 5, then (if necessary) at index 0, index 1, and so on. Introduced in 1.4.

void setDragEnabled(boolean) boolean getDragEnabled()

Set or get the property that determines whether automatic drag handling is enabled. See How to Use Drag and Drop and Data Transfer (page 545) for more details. Introduced in 1.4.

Examples That Use Lists

This table shows the examples that use JList and where those examples are described.

Example

Where Described

Notes

SplitPaneDemo

How to Use Split Panes (page 369)

Contains a single-selection, immutable list.

ListDemo

This section

Demonstrates how to add and remove items from a list at runtime.

ListDialog

This section and How to Use BoxLayout (page 462)

Implements a modal dialog with a single-selection list.

ListDataEventDemo

How to Write a List Data Listener (page 682)

Demonstrates listening for list data events on a list model.

ListSelectionDemo

How to Write a List Selection Listener (page 685)

Contains a list and a table that share the same selection model. You can dynamically choose the selection mode.

SharedModelDemo

Using Models (page 50)

Modifies ListSelectionDemo so that the list and table share the same data model.

CustomComboBoxDemo

Providing a Custom Renderer (page 181)

Shows how to provide a custom renderer for a combo box. Because lists and combo boxes use the same type of renderer, you can use what you learn there and apply it to lists. In fact, a list and a combo box can share a renderer.

 < Day Day Up > 

Категории