[Overview] [Sample] [User's Guide] [Tutorial] [Requirements] [Limitations] [API Documentation]


MultiColumnListbox
Tutorial

The following sample applet uses the MultiColumnListbox Bean to display a series of names and graphic status icons. The source code for this example is included as an introduction to using the MultiColumnListbox Bean. It is not meant to cover every possible way that the Bean can be used. Refer to the API Documentation for a complete list of available methods.

Note: Currently, no commercial web browsers support JDK 1.1. Therefore, this version of the MultiColumnListbox will not work in Netscape Navigator, Internet Explorer, and other web browsers. If you are using Sun's new HotJava browser or the JDK 1.1 AppletViewer, use the URL link of the image below.

[Link to Java 1.1 Applet]

Table of Contents


Building a Simple Listbox

We won't attempt to create the sample applet above in one step. Rather, we'll start small and then add the additional features such as column sorting and graphical elements.

There are three basic steps to set up a new listbox:

  1. Create a new MultiColumnListbox instance
  2. Add columns
  3. Add rows of data

Let's perform each step in turn:

  1.      // Create a new listbox
         MultiColumnListbox listbox = new MultiColumnListbox();
         
  2.      // Create three columns
         listbox.addColumn("#");
         listbox.addColumn("First");
         listbox.addColumn("Last");
    
         OR
    
         // Create three columns
         String columns[] = { "#", "First Name", "Last Name" };
         listbox.addColumns(columns);
         
  3.      // Some sample data
         Object rows[][] = { 
            { "2", "Andy",    "Clark" }, 
            { "1", "Carl",    "Danowski" }, 
            { "3", "Rich",    "Gutierrez" },
            { "2", "Eugene",  "Shumulinsky" },
            { "1", "Charlie", "Cleveland" },
            { "3", "Tad",     "Kollar" } 
            };
    
         // Add the data to the listbox
         for (int i = 0; i OR
    
         // Add the data to the listbox
         listbox.addRows(rows);
         

Notice that there are two different ways to create columns and add data to the listbox. Both methods are interchangable and are provided to simplify your work.

Inserting the previous code into the following applet creates a simple MultiColumnListbox with three columns and several rows of data.

    import java.awt.*;

    import COM.taligent.widget.*;

    // Applet
    public class SampleMultiColumnListbox
        extends java.applet.Applet 
        {
	//// SAMPLE DATA ////

        // Setup applet
        public void init() {

            setBackground(Color.lightGray);
            setLayout(new BorderLayout());

            //// SAMPLE CODE ////

            add("Center", listbox);

            setSize(180, 140);
            setVisible(true);
            }
        }

And that's it! You are finished if you only want to display rows of text information. If you want more than the basic listbox, however, you need to do a little more work. The following sections describe how to change column settings, capture listbox events, add graphical elements, and also introduce you to some advanced features of the listbox.

Setting Column Information

Now that we have created a few columns and filled them with data, let's modify some of the column attributes.

Let's allow the user to sort the First Name and Last Name columns. You can use any custom Sorter class you want but for our purposes we'll use the SelectionSorter provided. We also need to decide what comparison is to be used. Do we compare the elements as Strings? as Integers? Again, you can create your own custom Comparator, but the Sorter class, by default, compares String elements using the StringComparator provided, so that is what we'll use.

Column indexes, like row indexes, start at zero.

     //// assumes import COM.taligent.util.*; ////

     // Change settings for status column
     ListboxColumn column = listbox.getColumnInfo(0);
     column.setWidth(30);
     column.setResizable(false);

     // Change settings for first name column
     column = listbox.getColumnInfo(1);
     column.setSorter(new SelectionSorter());

     // Change settings for last name column
     column = listbox.getColumnInfo(2);
     column.setWidth(100);
     column.setSorter(new SelectionSorter());
     

The width of the status column is set to 30 and not resizable by the user. The First Name and Last Name columns are now sortable. In the next section we add event handling to enable our applet to catch events that are produced when the user manipulates the listbox.

Handling Events

The MultiColumnListbox follows the Java 1.1 event delegation model. Components implement listener interfaces and then register themselves with the Bean to receive event notifications.

The program using the MultiColumnListbox can receive events when the user selects or deselects rows and when the user selects or resizes a caption. A ListboxListener is notified of row selections and deselections. A CaptionBarListener is notified of caption selection and resizing.

Let's add implement the listbox listener interfaces and register the applet as a listener:

import COM.taligent.widget.event.*;

public class SampleMultiColumnListbox
    extends java.applet.Applet
    implements CaptionBarListener, ListboxListener
    {
    // Setup applet
    public void init() {

        //// SAMPLE CODE ////

        // Add listeners
        listbox.addCaptionBarListener(this);
        listbox.addListboxListener(this);
        }

    /** Column was selected. */
    public void captionSelected(CaptionBarEvent evt) {

        System.out.println(evt.toString());
        }

    /** Column was resized. */
    public void captionResized(CaptionBarEvent evt) {

        System.out.println(evt.toString());
        }

    /** Row was selected. */
    public void rowSelected(ListboxEvent evt) {

        System.out.println(evt.toString());
        }

    /** Row was deselected. */
    public void rowDeselected(ListboxEvent evt) {

        System.out.println(evt.toString());
        }

    }

The code marked in bold shows the applet implementing the listbox listeners. The code marked in red registers the applet as a listener instance with the listbox.

The listener methods will be called as the user interacts with the listbox and produces events. It it important to note that only user events are passed to the listeners. No events are passed when the program alters the listbox.

Graphic Elements

The MultiColumnListbox Bean can contain any graphical element you create that implements the Paintable interface. In this section we are going to replace the status numbers in the first column with graphic icons saved as transparent GIFs.

The StatusIcon class below implements Paintable so that we can draw the icon. It also implements Comparator so that we can use the same graphic object to sort the status column.

import java.awt.*;

public class StatusIcon
    extends Object
    implements COM.taligent.widget.Paintable, 
               COM.taligent.util.Comparator
    {
    // Data
    private Image image;
    private int   status;

    // Constructor.
    public StatusIcon(Image image, int status) {

        this.image  = image;
        this.status = status;
        }

    // Getters
    public Image getImage()  { return image; }
    public int   getStatus() { return status; }

    // Methods for Paintable interface
    public Dimension getSize()    { return new Dimension(20, 20); }
    public void paint(Graphics g) { g.drawImage(image, 0, 0, null); }

    // Method for Comparator interface
    public int compare(Object a, Object b) {
        int aval = ((StatusIcon)a).getStatus();
        int bval = ((StatusIcon)b).getStatus();

        if (aval  bval)
            return 1;

        return 0;
        }
    }

The Paintable interface requires us to define the getSize and paint methods in our object. The MultiColumnListbox Bean doesn't need to know what the size of the Paintable object is but the method is part of the interface for other classes that use Paintable objects and need to know the size of the element before painting them.

Tip: The graphics context that your Paintable object receives from the MultiColumnListbox when it is drawn only includes the area of the element in the listbox. You can provide your own centering and scaling of the Paintable object by first determining the size of the graphics context in the paint method. You can do this by calling getClipBounds. This method returns a Rectangle object with which you can extract the width and height information.

The Comparator interface required us to define the compare method which compares objects a and b and returns a negative number if a < b; a positive number if a > b; and zero if the two objects are equal to each other.

Once we have created the StatusIcon class, we need to load the images and add them to the listbox. We will do this in two steps.

  1.      //// assume import java.net.URL; ////
    
         // Load the status icons
         URL baseURL = getCodeBase();
         Image images[] = { 
             getImage(baseURL, "one.gif"),
             getImage(baseURL, "two.gif"),
             getImage(baseURL, "three.gif") 
             };
    
         StatusIcon icons[] = new StatusIcon[3];
         MediaTracker tracker = new MediaTracker(this);
    
         for (int i = 0; i 
    
  2.      // Status icons for names
         StatusIcon statusicons[] = { icons[1], icons[0], icons[2], 
                                      icons[1], icons[0], icons[2] };
    
         // Replace the status numbers with icons
         listbox.replaceColumn(statusicons, 0);
    
         // Allow status column to be sorted
         listbox.getColumnInfo(0)
             .setSorter(new SelectionSorter())
             .getSorter().setComparator(icons[0]);
    
         // Resort the listbox
         listbox.sort();
         

Other Features

The listbox has a few advanced features that are quite useful. One of these features is the ability to display multi-line captions in the caption bar. In addition, each row can display multi-line, text strings.

In order to display multi-line captions in the caption bar, you need to do two things:

  1. Use multi-line caption strings. To enable a multi-line caption heading, use a newline character ('\n') in the caption string. Change the following code:
         // Create three columns
         String columns[] = { "#", "First Name", "Last Name" };
         listbox.addColumns(columns);
         

    to:

         String columns[] = { "#", "First\nName", "Last\nName" };
         listbox.addColumns(columns);
         
  2. The caption bar does not automatically adjust the height based on the caption strings. You must set the height of the caption bar. For example:
         // Resize CaptionBar height
         listbox.setCaptionBarHeight(listbox.getCaptionBarHeight() * 2);
         

    This is the simplest way to enable the caption bar to display 2 line caption headers. However, you could use a multiple of the FontMetrics height of the listbox font to determine the caption bar height.

Setting the listbox to handle multi-line text element is
the same: use newline characters in your strings and set
the listbox row height using the setRowHeight(int)
method.


Another powerful feature of the listbox is its ability to include any Java Component as an element in the listbox.

Tip: the more Component elements you add, the more overhead you add to positioning and sizing those components. Use common sense and include components only where they are needed.

Let's add a handful of components to the sample applet. Change the sample data from:

     // Some sample data
     Object rows[][] = { 
        { "2", "Andy",    "Clark" }, 
        { "1", "Carl",    "Danowski" }, 
        { "3", "Rich",    "Gutierrez" },
        { "2", "Eugene",  "Shumulinsky" },
        { "1", "Charlie", "Cleveland" },
        { "3", "Tad",     "Kollar" } 
        };
to:

    // Some sample data
    Label     andy      = new Label("Andy");
    Checkbox  rich      = new Checkbox("Rich");
    Button    gutierrez = new Button("Gutierrez");
    TextField eugene    = new TextField("Eugene");
    Button    kollar    = new Button("Kollar");

    Object rows[][] = {
        { "2", andy,      "Clark"        },
        { "1", "Carl",    "Danowski"     },
        { "3", rich,      gutierrez      },
        { "2", eugene,    "Shumulinsky"  },
        { "1", "Charlie", "Cleveland"    },
        { "3", "Tad",     kollar         }
        };

Since the added AWT Components are standard components we can register the applet to listen to the various events that the components send out.

You are now ready to add the additional code, recompile, and view the applet. You will now see the same sample applet that is shown at the top of this page. To see everything put together, refer to the source code (SampleMultiColumnListbox.java).


Copyright Taligent, Inc. 1996 - 1997.
Copyright © IBM Corporation 1996 - 1997.
All Rights Reserved