Lists


If you want to present a set of choices to a user, and a radio button or checkbox set consumes too much space, you can use a combo box or a list. Combo boxes were covered in Volume 1 because they are relatively simple. The JList component has many more features, and its design is similar to that of the tree and table components. For that reason, it is our starting point for the discussion of complex Swing components.

Of course, you can have lists of strings, but you can also have lists of arbitrary objects, with full control of how they appear. The internal architecture of the list component that makes this generality possible is rather elegant. Unfortunately, the designers at Sun felt that they needed to show off that elegance, rather than hiding it from the programmer who just wants to use the component. You will find that the list control is somewhat awkward to use for common cases because you need to manipulate some of the machinery that makes the general cases possible. We walk you through the simple and most common case, a list box of strings, and then give a more complex example that shows off the flexibility of the list component.

The JList Component

The JList component is similar to a set of checkboxes or radio buttons, except that the items are placed inside a single box and are selected by clicking on the items themselves, not on buttons. If you permit multiple selection for a list box, the user can select any combination of the items in the box.

Figure 6-1 shows an admittedly silly example. The user can select the attributes for the fox, such as "quick," "brown," "hungry," "wild," and, because we ran out of attributes, "static," "private," and "final." You can thus have the static final fox jump over the lazy dog.

Figure 6-1. A list box


To construct this list component, you first start out with an array of strings, then pass the array to the JList constructor:

 String[] words= { "quick", "brown", "hungry", "wild", ... }; JList wordList = new JList(words); 

Alternatively, you can use an anonymous array:

 JList wordList = new JList(new String[] {"quick", "brown", "hungry", "wild", ... }); 

List boxes do not scroll automatically. To make a list box scroll, you must insert it into a scroll pane:

 JScrollPane scrollPane = new JScrollPane(wordList); 

You then add the scroll pane, not the list, into the surrounding panel.

We must admit that the separation of the list display and the scrolling mechanism is elegant in theory, but it is a pain in practice. Essentially all lists that we ever encountered needed scrolling. It seems cruel to force programmers to go through hoops in the default case just so they can appreciate that elegance.

By default, the list component displays eight items; use the setVisibleRowCount method to change that value:

 wordList.setVisibleRowCount(4); // display 4 items 

You can set the layout orientation to one of three values:

  • JList.VERTICAL (the default): arrange all items vertically

  • JList.VERTICAL_WRAP: start new columns if there are more items than the visible row count (see Figure 6-2)

    Figure 6-2. Lists with vertical and horizontal wrap


  • JList.HORIZONTAL_WRAP: start new columns if there are more items than the visible row count, but fill them horizontally. Look at the placement of the words "quick," "brown," and "hungry" in Figure 6-2 to see the difference between vertical and horizontal wrap.

By default, a user can select multiple items. This requires some knowledge of mouse technique: To add more items to a selection, press the CTRL key while clicking on each item. To select a contiguous range of items, click on the first one, then hold down the SHIFT key and click on the last one.

You can also restrict the user to a more limited selection mode with the setSelectionMode method:

 wordList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); \    // select one item at a time wordList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);    // select one item or one range of items 

You may recall from Volume 1 that the basic user interface components send out action events when the user activates them. List boxes use a different notification mechanism. Rather than listening to action events, you need to listen to list selection events. Add a list selection listener to the list component, and implement the method

 public void valueChanged(ListSelectionEvent evt) 

in the listener.

When the user selects items, a flurry of list selection events is generated. For example, suppose the user clicks on a new item. When the mouse button goes down, an event reports a change in selection. This is a transitional eventthe call

 event.isAdjusting() 

returns true if the selection is not yet final. Then, when the mouse button goes up, there is another event, this time with isAdjusting returning false. If you are not interested in the transitional events, then you can wait for the event for which isAdjusting is false. However, if you want to give the user instant feedback as soon as the mouse button is clicked, then you need to process all events.

Once you are notified that an event has happened, you will want to find out what items are currently selected. The getSelectedValues method returns an array of objects containing all selected items. Cast each array element to a string.


Object[] values = list.getSelectedValues();
for (Object value : values)
   do something with (String) value;

CAUTION

You cannot cast the return value of getSelectedValues from an Object[] array to a String[] array. The return value was not created as an array of strings, but as an array of objects, each of which happens to be a string. To process the return value as an array of strings, use the following code:

 int length = values.length; String[] words = new String[length]; System.arrayCopy(values, 0, words, 0, length); 


If your list does not allow multiple selections, you can call the convenience method getSelectedValue. It returns the first selected value (which you know to be the only value if multiple selections are disallowed).

 String value = (String) list.getSelectedValue(); 

NOTE

List components do not react to double clicks from a mouse. As envisioned by the designers of Swing, you use a list to select an item, and then you click a button to make something happen. However, some user interfaces allow a user to double-click on a list item as a shortcut for item selection and acceptance of a default action. If you want to implement this behavior, you have to add a mouse listener to the list box, then trap the mouse event as follows:

 public void mouseClicked(MouseEvent evt) {    if (evt.getClickCount() == 2)    {       JList source = (JList) evt.getSource();       Object[] selection = source.getSelectedValues();       doAction(selection);    } } 


Example 6-1 is the listing of the program that demonstrates a list box filled with strings. Notice how the valueChanged method builds up the message string from the selected items.

Example 6-1. ListTest.java
   1. import java.awt.*;   2. import java.awt.event.*;   3. import javax.swing.*;   4. import javax.swing.event.*;   5.   6. /**   7.    This program demonstrates a simple fixed list of strings.   8. */   9. public class ListTest  10. {  11.    public static void main(String[] args)  12.    {  13.       JFrame frame = new ListFrame();  14.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  15.       frame.setVisible(true);  16.    }  17. }  18.  19. /**  20.    This frame contains a word list and a label that shows a  21.    sentence made up from the chosen words. Note that you can  22.    select multiple words with Ctrl+click and Shift+click.  23. */  24. class ListFrame extends JFrame  25. {  26.    public ListFrame()  27.    {  28.       setTitle("ListTest");  29.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  30.  31.       String[] words =  32.       {  33.          "quick","brown","hungry","wild","silent",  34.          "huge","private","abstract","static","final"  35.       };  36.  37.       wordList = new JList(words);  38.       wordList.setVisibleRowCount(4);  39.       JScrollPane scrollPane = new JScrollPane(wordList);  40.  41.       listPanel = new JPanel();  42.       listPanel.add(scrollPane);  43.       wordList.addListSelectionListener(new  44.          ListSelectionListener()  45.          {  46.             public void valueChanged(ListSelectionEvent event)  47.             {  48.                Object[] values = wordList.getSelectedValues();  49.  50.                StringBuilder text = new StringBuilder(prefix);  51.                for (int i = 0; i < values.length; i++)  52.                {  53.                   String word = (String) values[i];  54.                   text.append(word);  55.                   text.append(" ");  56.                }  57.                text.append(suffix);  58.  59.                label.setText(text.toString());  60.             }  61.          });  62.  63.       buttonPanel = new JPanel();  64.       group = new ButtonGroup();  65.       makeButton("Vertical", JList.VERTICAL);  66.       makeButton("Vertical Wrap", JList.VERTICAL_WRAP);  67.       makeButton("Horizontal Wrap", JList.HORIZONTAL_WRAP);  68.  69.       add(listPanel, BorderLayout.NORTH);  70.       label = new JLabel(prefix + suffix);  71.       add(label, BorderLayout.CENTER);  72.       add(buttonPanel, BorderLayout.SOUTH);  73.    }  74.  75.    /**  76.       Makes a radio button to set the layout orientation.  77.       @param label the button label  78.       @param orientation the orientation for the list  79.    */  80.    private void makeButton(String label, final int orientation)  81.    {  82.       JRadioButton button = new JRadioButton(label);  83.       buttonPanel.add(button);  84.       if (group.getButtonCount() == 0) button.setSelected(true);  85.       group.add(button);  86.       button.addActionListener(new  87.          ActionListener()  88.          {  89.             public void actionPerformed(ActionEvent event)  90.             {  91.                wordList.setLayoutOrientation(orientation);  92.                listPanel.revalidate();  93.             }  94.          });  95.    }  96.  97.    private static final int DEFAULT_WIDTH = 400;  98.    private static final int DEFAULT_HEIGHT = 300;  99.    private JPanel listPanel; 100.    private JList wordList; 101.    private JLabel label; 102.    private JPanel buttonPanel; 103.    private ButtonGroup group; 104.    private String prefix = "The "; 105.    private String suffix = "fox jumps over the lazy dog."; 106. } 


 javax.swing.JList 1.2 

  • JList(Object[] items)

    constructs a list that displays these items.

  • int getVisibleRowCount()

  • void setVisibleRowCount(int c)

    get or set the preferred number of rows in the list that can be displayed without a scroll bar.

  • int getLayoutOrientation() 1.4

  • void setLayoutOrientation(int orientation) 1.4

    get or set the layout orientation

    Parameters:

    orientation

    One of VERTICAL, VERTICAL_WRAP, HORIZONTAL_WRAP


  • int getSelectionMode()

  • void setSelectionMode(int mode)

    get or set the mode that determines whether single-item or multiple-item selections are allowed.

    Parameters:

    mode

    One of SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, MULTIPLE_INTERVAL_SELECTION


  • void addListSelectionListener(ListSelectionListener listener)

    adds to the list a listener that's notified each time a change to the selection occurs.

  • Object[] getSelectedValues()

    returns the selected values or an empty array if the selection is empty.

  • Object getSelectedValue()

    returns the first selected value or null if the selection is empty.


 javax.swing.event.ListSelectionListener 1.2 

  • void valueChanged(ListSelectionEvent e)

    is called whenever the list selection changes.

List Models

In the preceding section, you saw the most common method for using a list component:

  • Specify a fixed set of strings for display in the list,

  • Place the list inside a scroll pane, and

  • Trap the list selection events.

In the remainder of the section on lists, we cover more complex situations that require a bit more finesse:

  • Very long lists

  • Lists with changing contents

  • Lists that don't contain strings

In the first example, we constructed a JList component that held a fixed collection of strings. However, the collection of choices in a list box is not always fixed. How do we add or remove items in the list box? Somewhat surprisingly, there are no methods in the JList class to achieve this. Instead, you have to understand a little more about the internal design of the list component. As with text components, the list component uses the model-view-controller design pattern to separate the visual appearance (a column of items that are rendered in some way) from the underlying data (a collection of objects).

The JList class is responsible for the visual appearance of the data. It actually knows very little about how the data are storedall it knows is that it can retrieve the data through some object that implements the ListModel interface:

 public interface ListModel {    int getSize();    Object getElementAt(int i);    void addListDataListener(ListDataListener l);    void removeListDataListener(ListDataListener l); } 

Through this interface, the JList can get a count of elements and retrieve each one of the elements. Also, the JList object can add itself as a list data listener. That way, if the collection of elements changes, JList gets notified so that it can repaint the list.

Why is this generality useful? Why doesn't the JList object simply store a vector of objects?

Note that the interface doesn't specify how the objects are stored. In particular, it doesn't force them to be stored at all! The getElementAt method is free to recompute each value whenever it is called. This is potentially useful if you want to show a very large collection without having to store the values.

Here is a somewhat silly example: We let the user choose among all three-letter words in a list box (see Figure 6-3).

Figure 6-3. Choosing from a very long list of selections


There are 26 x 26 x 26 = 17,576 three-letter combinations. Rather than storing all these combinations, we recompute them as requested when the user scrolls through them.

This turns out to be easy to implement. The tedious part, adding and removing listeners, has been done for us in the AbstractListModel class, which we extend. We only need to supply the getSize and getElementAt methods:

 class WordListModel extends AbstractListModel {    public WordListModel(int n) { length = n; }    public int getSize() { return (int) Math.pow(26, length); }    public Object getElementAt(int n)    {       // compute nth string       . . .    }    . . . } 

The computation of the nth string is a bit technicalyou'll find the details in the code listing in Example 6-2.

Now that we have supplied a model, we can simply build a list that lets the user scroll through the elements supplied by the model:

 JList wordList = new JList(new WordListModel(3)); wordList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane scrollPane = new JScrollPane(wordList); 

The point is that the strings are never stored. Only those strings that the user actually requests to see are generated.

We must make one other setting. We must tell the list component that all items have a fixed width and height. The easiest way to set the cell dimensions is to specify a prototype cell value:

 wordList.setPrototypeCellValue("www"); 

The prototype cell value is used to determine the size for all cells. Alternatively, you can set a fixed cell size:

 wordList.setFixedCellWidth(50); wordList.setFixedCellHeight(15); 

If you don't set a prototype value or a fixed cell size, the list component computes the width and height of each item. That would take a long time.

As a practical matter, very long lists are rarely useful. It is extremely cumbersome for a user to scroll through a huge selection. For that reason, we believe that the list control has been completely overengineered. A selection that a user can comfortably manage on the screen is certainly small enough to be stored directly in the list component. That arrangement would have saved programmers from the pain of having to deal with the list model as a separate entity. On the other hand, the JList class is consistent with the Jtree and JTable class where this generality is useful.

Example 6-2. LongListTest.java
   1. import java.awt.*;   2. import java.awt.event.*;   3. import javax.swing.*;   4. import javax.swing.event.*;   5.   6. /**   7.    This program demonstrates a list that dynamically computes   8.    list entries.   9. */  10. public class LongListTest  11. {  12.    public static void main(String[] args)  13.    {  14.       JFrame frame = new LongListFrame();  15.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  16.       frame.setVisible(true);  17.    }  18. }  19.  20. /**  21.    This frame contains a long word list and a label that shows a  22.    sentence made up from the chosen word.  23. */  24. class LongListFrame extends JFrame  25. {  26.    public LongListFrame()  27.    {  28.       setTitle("LongListTest");  29.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  30.  31.       wordList = new JList(new WordListModel(3));  32.       wordList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);  33.       wordList.setPrototypeCellValue("www");  34.       JScrollPane scrollPane = new JScrollPane(wordList);  35.  36.       JPanel p = new JPanel();  37.       p.add(scrollPane);  38.       wordList.addListSelectionListener(new  39.          ListSelectionListener()  40.          {  41.             public void valueChanged(ListSelectionEvent evt)  42.             {  43.                StringBuilder word = (StringBuilder) wordList.getSelectedValue();  44.                setSubject(word.toString());  45.             }  46.  47.          });  48.  49.       Container contentPane = getContentPane();  50.       contentPane.add(p, BorderLayout.NORTH);  51.       label = new JLabel(prefix + suffix);  52.       contentPane.add(label, BorderLayout.CENTER);  53.       setSubject("fox");  54.    }  55.  56.    /**  57.       Sets the subject in the label.  58.       @param word the new subject that jumps over the lazy dog  59.    */  60.    public void setSubject(String word)  61.    {  62.       StringBuilder text = new StringBuilder(prefix);  63.       text.append(word);  64.       text.append(suffix);  65.       label.setText(text.toString());  66.    }  67.  68.    private static final int DEFAULT_WIDTH = 400;  69.    private static final int DEFAULT_HEIGHT = 300;  70.    private JList wordList;  71.    private JLabel label;  72.    private String prefix = "The quick brown ";  73.    private String suffix = " jumps over the lazy dog.";  74. }  75.  76. /**  77.    A model that dynamically generates n-letter words.  78. */  79. class WordListModel extends AbstractListModel  80. {  81.    /**  82.       Constructs the model.  83.       @param n the word length  84.    */  85.    public WordListModel(int n) { length = n; }  86.  87.    public int getSize()  88.    {  89.       return (int) Math.pow(LAST - FIRST + 1, length);  90.    }  91.  92.    public Object getElementAt(int n)  93.    {  94.       StringBuilder r = new StringBuilder();;  95.       for (int i = 0; i < length; i++)  96.       {  97.          char c = (char)(FIRST + n % (LAST - FIRST + 1));  98.          r.insert(0, c);  99.          n = n / (LAST - FIRST + 1); 100.       } 101.       return r; 102.    } 103. 104.    private int length; 105.    public static final char FIRST = 'a'; 106.    public static final char LAST = 'z'; 107. } 


 javax.swing.JList 1.2 

  • JList(ListModel dataModel)

    constructs a list that displays the elements in the specified model.

  • void setPrototypeCellValue(Object newValue)

  • Object getPrototypeCellValue()

    set or get the prototype cell value that is used to determine the width and height of each cell in the list. The default is null, which forces the size of each cell to be measured.

  • void setFixedCellWidth(int width)

    if the width is greater than zero, specifies the width of every cell in the list. The default value is -1, which forces the size of each cell to be measured.

  • void setFixedCellHeight(int height)

    if the height is greater than zero, specifies the height of every cell in the list. The default value is -1, which forces the size of each cell to be measured.


 javax.swing.ListModel 1.2 

  • int getSize()

    returns the number of elements of the model.

  • Object getElementAt(int position)

    returns an element of the model at the given position.

Inserting and Removing Values

You cannot directly edit the collection of list values. Instead, you must access the model and then add or remove elements. That, too, is easier said than done. Suppose you want to add more values to a list. You can obtain a reference to the model:

 ListModel model = list.getModel(); 

But that does you no goodas you saw in the preceding section, the ListModel interface has no methods to insert or remove elements because, after all, the whole point of having a list model is that it need not store the elements.

Let's try it the other way around. One of the constructors of JList takes a vector of objects:

 Vector<String> values = new Vector<String>(); values.addElement("quick"); values.addElement("brown"); . . . JList list = new JList(values); 

You can now edit the vector and add or remove elements, but the list does not know that this is happening, so it cannot react to the changes. In particular, the list cannot update its view when you add the values. Therefore, this constructor is not very useful.

Instead, you should construct a DefaultListModel object, fill it with the initial values, and associate it with the list.

 DefaultListModel model = new DefaultListModel(); model.addElement("quick"); model.addElement("brown"); . . . JList list = new JList(model); 

Now you can add or remove values from the model object. The model object then notifies the list of the changes, and the list repaints itself.

 model.removeElement("quick"); model.addElement("slow"); 

For historical reasons, the DefaultListModel class doesn't use the same method names as the collection classes.

The default list model uses a vector internally to store the values.

CAUTION

There are JList constructors that construct a list from an array or vector of objects or strings. You might think that these constructors use a DefaultListModel to store these values. That is not the casethe constructors build a trivial model that can access the values without any provisions for notification if the content changes. For example, here is the code for the constructor that constructs a JList from a Vector:

 public JList(final Vector<?> listData) {    this (new AbstractListModel()    {       public int getSize() { return listData.size(); }       public Object getElementAt(int i) { return listData.elementAt(i); }    }); } 

That means, if you change the contents of the vector after the list is constructed, then the list may show a confusing mix of old and new values until it is completely repainted. (The keyword final in the constructor above does not prevent you from changing the vector elsewhereit only means that the constructor itself won't modify the value of the listData reference; the keyword is required because the listData object is used in the inner class.)



 javax.swing.JList 1.2 

  • ListModel getModel()

    gets the model of this list.


 javax.swing.DefaultListModel 1.2 

  • void addElement(Object obj)

    adds the object to the end of the model.

  • boolean removeElement(Object obj)

    removes the first occurrence of the object from the model. Returns true if the object was contained in the model, false otherwise.

Rendering Values

So far, all lists that you saw in this chapter contained only strings. It is actually just as easy to show a list of iconssimply pass an array or vector filled with Icon objects. More interestingly, you can easily represent your list values with any drawing whatsoever.

Although the JList class can display strings and icons automatically, you need to install a list cell renderer into the JList object for all custom drawing. A list cell renderer is any class that implements the following interface:

 interface ListCellRenderer {    Component getListCellRendererComponent(JList list, Object value, int index,       boolean isSelected, boolean cellHasFocus); } 

This method is called for each cell. It returns a component that paints the cell contents. The component is placed at the appropriate location whenever a cell needs to be rendered.

One way to implement a cell renderer is to create a class that extends JPanel, like this:

 class MyCellRenderer extends JPanel implements ListCellRenderer {    public Component getListCellRendererComponent(JList list, Object value, int index,       boolean isSelected, boolean cellHasFocus)    {       // stash away information that is needed for painting and size measurement       return this;    }    public void paintComponent(Graphics g)    {       // paint code goes here    }    public Dimension getPreferredSize()    {       // size measurement code goes here    }    // instance fields } 

In Example 6-3, we display the font choices graphically by showing the actual appearance of each font (see Figure 6-4). In the paintComponent method, we display each name in its own font. We also need to make sure to match the usual colors of the look and feel of the JList class. We obtain these colors by calling the getForeground/getBackground and getSelectionForeground/getSelectionBackground methods of the JList class. In the getPreferredSize method, we need to measure the size of the string, using the techniques that you saw in Volume 1, Chapter 7.

Figure 6-4. A list box with rendered cells


To install the cell renderer, simply call the setCellRenderer method:

 fontList.setCellRenderer(new FontCellRenderer()); 

Now all list cells are drawn with the custom renderer.

Actually, a simpler method for writing custom renderers works in many cases. If the rendered image just contains text, an icon, and possibly a change of color, then you can get by with configuring a JLabel. For example, to show the font name in its own font, we can use the following renderer:

 class FontCellRenderer extends JLabel implements ListCellRenderer {    public Component getListCellRendererComponent(JList list, Object value, int index,       boolean isSelected, boolean cellHasFocus)    {       JLabel label = new JLabel();       Font font = (Font) value;       setText(font.getFamily());       setFont(font);       setOpaque(true);       setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());       setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());       return this;    } } 

Note that here we don't write any paintComponent or getPreferredSize methods; the JLabel class already implements these methods to our satisfaction. All we do is configure the label appropriately by setting its text, font, and color.

This code is a convenient shortcut for those cases in which an existing componentin this case, JLabelalready provides all functionality needed to render a cell value.

CAUTION

It is not a good idea to construct a new component in each call to getListCellRendererComponent. If the user scrolls through many list entries, a new component would be constructed every time. Reconfiguring an existing component is safe and much more efficient.


Example 6-3. ListRenderingTest.java
   1. import java.util.*;   2. import java.awt.*;   3. import java.awt.event.*;   4. import javax.swing.*;   5. import javax.swing.event.*;   6.   7. /**   8.    This program demonstrates the use of cell renderers in   9.    a list box.  10. */  11. public class ListRenderingTest  12. {  13.    public static void main(String[] args)  14.    {  15.       JFrame frame = new ListRenderingFrame();  16.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  17.       frame.setVisible(true);  18.    }  19. }  20.  21. /**  22.    This frame contains a list with a set of fonts and a text  23.    area that is set to the selected font.  24. */  25. class ListRenderingFrame extends JFrame  26. {  27.    public ListRenderingFrame()  28.    {  29.       setTitle("ListRenderingTest");  30.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  31.  32.       ArrayList<Font> fonts = new ArrayList<Font>();  33.       final int SIZE = 24;  34.       fonts.add(new Font("Serif", Font.PLAIN, SIZE));  35.       fonts.add(new Font("SansSerif", Font.PLAIN, SIZE));  36.       fonts.add(new Font("Monospaced", Font.PLAIN, SIZE));  37.       fonts.add(new Font("Dialog", Font.PLAIN, SIZE));  38.       fonts.add(new Font("DialogInput", Font.PLAIN, SIZE));  39.       fontList = new JList(fonts.toArray());  40.       fontList.setVisibleRowCount(4);  41.       fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);  42.       fontList.setCellRenderer(new FontCellRenderer());  43.       JScrollPane scrollPane = new JScrollPane(fontList);  44.  45.       JPanel p = new JPanel();  46.       p.add(scrollPane);  47.       fontList.addListSelectionListener(new  48.          ListSelectionListener()  49.          {  50.             public void valueChanged(ListSelectionEvent evt)  51.             {  52.                Font font = (Font) fontList.getSelectedValue();  53.                text.setFont(font);  54.             }  55.  56.          });  57.  58.       Container contentPane = getContentPane();  59.       contentPane.add(p, BorderLayout.SOUTH);  60.       text = new JTextArea("The quick brown fox jumps over the lazy dog");  61.       text.setFont((Font) fonts.get(0));  62.       text.setLineWrap(true);  63.       text.setWrapStyleWord(true);  64.       contentPane.add(text, BorderLayout.CENTER);  65.    }  66.  67.    private JTextArea text;  68.    private JList fontList;  69.    private static final int DEFAULT_WIDTH = 400;  70.    private static final int DEFAULT_HEIGHT = 300;  71. }  72.  73. /**  74.    A cell renderer for Font objects that renders the font name in its own font.  75. */  76. class FontCellRenderer extends JPanel implements ListCellRenderer  77. {  78.    public Component getListCellRendererComponent(JList list, Object value, int index,  79.       boolean isSelected, boolean cellHasFocus)  80.    {  81.       font = (Font) value;  82.       background = isSelected ? list.getSelectionBackground() : list.getBackground();  83.       foreground = isSelected ? list.getSelectionForeground() : list.getForeground();  84.       return this;  85.    }  86.  87.    public void paintComponent(Graphics g)  88.    {  89.       String text = font.getFamily();  90.       FontMetrics fm = g.getFontMetrics(font);  91.       g.setColor(background);  92.       g.fillRect(0, 0, getWidth(), getHeight());  93.       g.setColor(foreground);  94.       g.setFont(font);  95.       g.drawString(text, 0, fm.getAscent());  96.    }  97.  98.    public Dimension getPreferredSize()  99.    { 100.       String text = font.getFamily(); 101.       Graphics g = getGraphics(); 102.       FontMetrics fm = g.getFontMetrics(font); 103.       return new Dimension(fm.stringWidth(text), fm.getHeight()); 104.    } 105. 106.    private Font font; 107.    private Color background; 108.    private Color foreground; 109. } 


 javax.swing.JList 1.2 

  • Color getBackground()

    returns the background color for unselected cells.

  • Color getSelectionBackground()

    returns the background color for selected cells.

  • Color getForeground()

    returns the foreground color for unselected cells.

  • Color getSelectionForeground()

    returns the foreground color for selected cells.

  • void setCellRenderer(ListCellRenderer cellRenderer)

    sets the renderer that paints the cells in the list.


 javax.swing.ListCellRenderer 1.2 

  • Component getListCellRendererComponent(JList list, Object item, int index, boolean isSelected, boolean hasFocus)

    returns a component whose paint method draws the cell contents. If the list cells do not have fixed size, that component must also implement getPreferredSize.

    Parameters:

    list

    The list whose cell is being drawn

     

    item

    The item to be drawn

     

    index

    The index where the item is stored in the model

     

    isSelected

    TRue if the specified cell was selected

     

    hasFocus

    true if the specified cell has the focus




    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net