Java Programming   Java Programming
 |Sofia Home | Content Gallery |
Home
Syllabus
Schedule
Lessons
Assignments
Resources

Lesson 12.4 Lists

Lists & Choices

Java has two user-interface components that allow your user to select from several different alternatives, presented as regular, natural-language, descriptions. In this section, you'll learn about these two classes: the Choice and the List.

A Choice is a drop-down list containing Strings. In the Windows universe, this control is normally known as a combo box.

The Choice class has only a single, no-argument constructor, so you can't populate a Choice object at the same time you create it. Instead, you use one of Choice methods to add Strings to the Choice during your constructor or init() method.

To populate your Choice, you can use one of three methods:

add(String);
addItem(String);
insert(String, int);

The methods add() and addItem() are identical. [Why? Who knows!]. Both add the new String at the end of the items stored in the Choice.

The insert() method treats the Choice as a zero-based array of Strings and inserts the specific item at the requested location. All the rest of the items are moved down to make room for the inserted String.

Here's a very simple example that uses a Choice, taken from a hypothetical applet designed to teach nutrition:
SimpleChoice.java
import java.awt.*;
import java.applet.*;

public class SimpleChoice extends Applet
{
  Choice foods = new Choice();

  public void init()
  {
    foods.add("Spam");
    foods.addItem("Abazaba");
    foods.insert("Coffee", 0);

    add(foods);
  }
}

Back to Top

Working with Choices

When you first populate a Choice, the first item added will normally be the selected item. The selected item is the item that is displayed in the Choice when the Choice is "closed."

You can change the selected item by inserting a new item in position 0, [as with "Coffee" in the SimpleChoice applet], or you can explicitly select an item using the select() method.

When you use the select() method you may specify the item's index [starting from zero] like this:

foods.select(2); // Abazaba

You can also pass a String to the select() method like this:

foods.select("Spam");

If several items have the same String value, only the first is selected. If you try to select a String that is not in the Choice, then the selected item doesn't change.

Retrieving Values

The Choice class has two methods that allow you to retrieve the selected item from the Choice. The getSelectedIndex() method returns the  int index of the selected item, and the getSelectedItem() returns the String itself.

Here's an applet that puts the getSelectedItem() method to work creating witty phrases. The possibilities for expanding this applet are almost endless: term papers, greeting cards, business proposals, legislative analysis, and situation comedy scripts.
TestChoice.java
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class TestChoice extends Applet
    implements ActionListener
{
  private Choice person = new Choice();
  private Choice verb   = new Choice();
  private Choice adverb = new Choice();

  private Button phrase = new Button("Construct Phrase");
  private TextArea ta   = new TextArea();

  public void init()
  {
    setLayout(new BorderLayout());
    phrase.addActionListener(this);        
    Panel p = new Panel();
    // Person
    person.addItem("Fred");
    person.addItem("Wilma");
    person.addItem("Barney");
    person.addItem("Betty");
    person.addItem("Dino");
    p.add(person);

    // Verb
    verb.addItem("dances");
    verb.addItem("dines");
    verb.addItem("sings");
    verb.addItem("draws");
    verb.addItem("drives");
    p.add(verb);

    adverb.addItem("divinely");
    adverb.addItem("hungrily");
    adverb.addItem("quickly");
    adverb.addItem("sublimely");
    p.add(adverb);

    add("North", p);
    add("Center", ta);
    add("South", phrase);
  }

  public void actionPerformed(ActionEvent ae)
  {
    if (ae.getSource() == phrase)
    {
      ta.append(person.getSelectedItem()+" "+
                verb.getSelectedItem() + " "+
                adverb.getSelectedItem() + "\n");
    }
  }
}

Back to Top

Choice Events

The TestChoice example doesn't do anything when a new item is selected from one of the Choice objects; it only takes action when its Button is pressed. In Java 1.1, Choice objects generate ItemEvents, like radio buttons and checkboxes. 

To respond to these ItemEvents you write an itemStateChanged() method. Inside your method you can use the ItemEvent getSource() method to identify the Choice that triggered the event, and then use either of the retrieval methods to get the selected item from the Choice.

Here's the itemStateChanged() method from the FontChoice applet which displays each of the "logical" Java fonts available on your platform, and then displays the name in 36-point bold type, using the particular font selected.
public void itemStateChanged(ItemEvent ae)
{
  Choice ch = (Choice) ae.getSource();

  String name = ch.getSelectedItem();
  Font f = new Font(name, Font.BOLD, 36);

  display.setFont(f);
  display.setText(name);
}

SuperScrawler Choice

Let's take a few minutes to look ahead to how you'll use the Choice component in the SuperScrawler applet you'll be writing for your homework. 

In the Scrawler applet, which you'll be using as a "launching pad", the thickness of the drawing pen is stored in an int called penWidth

One of the components you're going to add is a Choice object called thickness, and it will contain Strings like "1 Pixel", "4 Pixels" and so forth. When a user selects a different pen thickness from your Choice, it will trigger an "item" event, which you'll intercept in the itemStateChanged() method which already exists.

Inside SuperScrawler's itemStateChanged() method, first check to see if the Choice thickness triggered the event. [Use ev.getSource()]. If it did, then use getSelectedItem() to retrieve the users' selection and an if-else-if to set the penWidth variable. 

[When you do this, remember that getSelectedItem() returns a String, so you'll have to use the equals() method, not the equality operator ==, to make your tests.]

Back to Top

The List Class

A close relative of the Choice class is the List. A List is like a Choice, but always open. 

Use a List instead of a Choice when users need to see several items at a time in context, instead of the single item that a Choice allows. A List is also called for if users need to select more than a single item at a time.

Constructing a List

Unlike the Choice which offers only a single constructor, the List class offers three:

List a = new List();
List b = new List(10);
List c = new List(12, true);

When you create a List you must specify how many rows of text are visible at once. The default [no argument] constructor creates a List that displays four rows. Examples b and c above create List objects that display 10 and 12 rows respectively.

The two-argument constructor [example c] also allows you to specify whether the list should allow multiple selections. Passing false restricts the List to single selection; if you pass true, the users can select several items at once.

Rows in a List
Although the List constructors require you to specify the number of visible rows in your List, in reality, this number is more or less meaningless. The actual number of rows displayed depends upon the size of your application or applet and the layout manger you use. Once you specify the number of rows for your List, you can't change it later.

In theory, the FlowLayout layout manager will respect the number of rows specified when the List is created, but in practice this varies widely from platform to platform. The width of a List is also highly platform dependent; the best advice is to use your layout manager to size your Lists and not rely on the preferred size mechanism.

List Methods

To populate a List, you use the add() method or the addItem() method. Like the Choice class, both these methods are identical. Unlike the Choice class, each comes in one and two-argument versions:

lst.add(String);          // at end
lst.add(String, int pos); // at pos

This second version of add() and addItem() does the same thing that the Choice insert() method does.

Back to Top

Retrieving and Removing Items

Like the Choice class, there are two methods for retrieving the currently selected item in a List. The getSelectedItem() method returns the String that is currently selected, while the getSelectedIndex() returns the zero-based index of the current selection.

Lists are slightly more complex than Choices, however, for two reasons:

  • A Choice will always have a selected value, thus getSelectedItem() and getSelectedIndex() cannot fail. That's not true for a List. If no items are selected in a List, then getSelectedItem() returns null, and getSelectedIndex() returns -1.
  • Unlike a Choice, a List has both a single-selection mode and a multi-selection mode. You can find out which mode the List is in by calling the isMultipleMode() method. 
To retrieve the values from a List in multiple-mode the List class has two additional methods: getSelectedIndexes() and getSelectedItems(). The first returns an array of int indexes, and the second returns an array of Strings representing the selected items. If no items are selected, then the length of the array will be 0, but the array will still be a valid array.

You can also remove an item from a list by using the remove() method. This method is overloaded, so you can write:

lst.remove(2); // 3rd item
lst.remove("Spam");

Both methods throw an exception if the index is out of bounds or if the String specified is not in the List.

List Events

Unlike the Choice class, List objects generate both ItemEvents and ActionEvents. ItemEvents are generated whenever an item is selected or deselected. An ActionEvent is generated whenever a List item is double-clicked.

Let's take a quick look at how this works. Rather than looking at the entire FontList applet, we'll concentrate on the event handling code. 

The FontList applet contains two List objects named left and right, and two Buttons named moveLeft and moveRight. Both of the Lists allow multiple selections, and, when the program starts, the left List is filled with the names of each of the logical fonts on your system.

If you select, or deselect, one of the fonts listed in either List, its name appears in your browser's status bar, along with its selection status. This is triggered by an ItemEvent which is handled in the itemStateChanged() method.

If you double-click one of the items in the List, it is copied to the other List, and removed from its previous abode. If you press the moveLeft or moveRight buttons, all of the selected items are copied to the opposite List box. Each of these events are carried out in the actionPerformed() method.

Before we look at the event-handling code, take a moment to look at the applet itself:

Back to Top

ItemEvents

ItemEvents are generated whenever the selection status of an item in a ListBox changes, usually by being clicked with the mouse. 

To receive these event notifications, you must first tell each List to send you the messages using addItemListener(). Here's the code that does this from FontList.java:

left.addItemListener(this);
right.addItemListener(this);

For this to work, your class must add implements ItemListener to its header, otherwise you'll get a syntax error.

Once you've told your List objects to notify you when an ItemEvent occurs, you have to give them some place to send the messages to. That "some place" is a method called itemStateChanged(), which takes an ItemEvent as its only argument.

Inside FontList's itemStateChanged() method, you need to do five things:

1. You need to find out which List generated the event. You can do that with the getSource() method. You have to cast the Object returned by getSource() to a List like this:

    public void itemStateChanged(ItemEvent ie)
    {
      // 1. List that generated the event
      List lst = (List) ie.getSource();
    }

2. The next step is to find out exactly which item on the list was selected. You can do that by using the ItemEvent getItem() method. Don't confuse this with the List getItem() method. The ItemEvent version returns an Object which you have to cast to the appropriate type. For ItemEvents generated by the List class, the appropriate type is Integer, which you can convert to an int index like this:

    // 2. Index of item selected or deselected
    Integer sel = (Integer) ie.getItem();
    int idx = sel.intValue();

3. The third step is to use the index computed in Step 2 to ask the List object [lst] to give you the String representing the selected item. You can do that with the List getItem() method:

    // 3. String of item selected or deselected
    String str = lst.getItem(idx);

4. The fourth step is to determine just what happened to the item. You can do that with the ItemEvent method getStateChange(). If the item was selected you'll get back ItemEvent.SELECTED. Otherwise you'll get back ItemEvent.DESELECTED. Here's how you code this piece of the puzzle:

    // 4. State of item
    boolean on = 
       (ie.getStateChange() == ItemEvent.SELECTED);

5. The final step is to take all of this information and combine it in a String that can be displayed using showStatus(), which displays information in your Web browser's status bar. Here's the code:

    // 5. Report on event that happend
    showStatus(""+ str + " was " + 
              (on ? "selected" : "deselected"));
Back to Top

ActionEvents

Handling the ActionEvents is a little simpler. 

The first step is to find out what object fired the event and retrieve the "action command" String. This code goes in the actionPerformed() method like this:

public void actionPerformed(ActionEvent ae)
{
  // 1. Who fired the event?
  Object o = ae.getSource();
  String cmd = ae.getActionCommand();
}

If the event was generated by one of the List objects, then you have to copy a single item from one List to the other. That can be handled in a single block of code that looks like this:

// 2. Handle list box double-clicks
if (o == left)
{
  right.add(cmd);
  left.remove(cmd);
}
else if (o == right)
{
  left.add(cmd);
  right.remove(cmd);
}

Finally, if one of the Buttons was pressed you need to retrieve all of the selected items from the appropriate List and copy it to the other. That's easily done with these few lines of code:

// 3. Handle the buttons
else if (o == mvRight || o == mvLeft)
{
  List src  = (o == mvRight ? left : right );
  List dest = (o == mvRight ? right: left  );

  String[] selected = src.getSelectedItems();
  for (int i = 0; i < selected.length; i++)
  {
    dest.add(selected[i]);
    src.remove(selected[i]);
  }
}

Back to Top

Something to Talk About

Why don't you try this? Here is some partially completed code for a simple List and a Label. What code do you have to add to display the selected item in the Label when the item in the List is double-clicked? 

[Your code should work like the applet shown below]
import java.awt.*;
import java.applet.*;
import java.awt.event.*;

public class Wrapup12d extends Applet
             implements ActionListener
{
  private List  lst = new List();
  private Label lbl = new Label();

  public void init()
  {
    setLayout(new BorderLayout());
    add(lst, "Center");
    add(lbl, "North");

    lst.add("Coffee");
    lst.add("Spam");
    lst.add("Abazaba");
    lst.addActionListener(this);
  }

  // Write this stuff here
}

Please continue to the next section of this lesson.

 

Back to Top

 

Content Developed by Stephen Gilbert, Licensed under a Creative Commons License
Published by the Sofia Open Content Initiative
© 2004 Foothill-De Anza Community College District &The William and Flora Hewlett Foundation