_chapter 6.htm

来自「Core Java 2(中文名称:JAVA 2 核心技术 卷二:高级特性)这是英」· HTM 代码 · 共 1,429 行 · 第 1/5 页

HTM
1,429
字号
  size of each cell to be measured.</li>
</ul>
<h5 class="docSection3Title" id="ch06lev3sec4"><tt>javax.swing.ListModel</tt></h5>
<p><img alt="graphics/api.gif" src="api.gif" border="0" width="46" height="45"><br>
&nbsp;</p>
<ul>
  <li>
  <p class="docList"><tt>int getSize()</tt></p>
  <p class="docList">returns the number of elements of the model.</li>
  <li>
  <p class="docList"><tt>Object getElementAt(int index)</tt></p>
  <p class="docList">returns an element of the model.</li>
</ul>
<h4 class="docSection2Title" id="ch06lev2sec3">Inserting and Removing Values</h4>
<p class="docText">You cannot directly edit the collection of list values. 
Instead, you must access the <span class="docEmphasis">model</span> 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:</p>
<pre>ListModel model = list.getModel();
</pre>
<p class="docText">But that does you no good梐s you saw in the preceding 
section, the <tt>ListModel</tt> interface has no methods to insert or remove 
elements since, after all, the whole point of having a list model is that it 
need not <span class="docEmphasis">store</span> the elements.</p>
<p class="docText">Let's try it the other way around. One of the constructors of
<tt>JList</tt> takes a vector of objects:</p>
<pre>Vector values = new Vector();
values.addElement(&quot;quick&quot;);
values.addElement(&quot;brown&quot;);
. . .
JList list = new JList(values);
</pre>
<p class="docText">Of course, 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.</p>
<div class="docNote">
  <p class="docNoteTitle">NOTE</p>
  <table cellSpacing="0" cellPadding="1" width="90%" border="0">
    <tr>
      <td vAlign="top" width="60">
      <img alt="graphics/note.gif" src="note.gif" align="left" border="0" width="54" height="53"><br>
&nbsp;</td>
      <td vAlign="top">
      <p class="docText">There is no <tt>JList</tt> constructor that takes an
      <tt>ArrayList</tt> parameter. But, since construction from a <tt>Vector</tt> 
      isn't all that useful, that's not a real limitation.</td>
    </tr>
  </table>
</div>
<p class="docText">Instead, you have to construct a particular model, the <tt>
DefaultListModel</tt>, fill it with the initial values, and associate it with 
the list.</p>
<pre>DefaultListModel model = new DefaultListModel();
model.addElement(&quot;quick&quot;);
model.addElement(&quot;brown&quot;);
. . .
JList list = new JList(model);
</pre>
<p class="docText">Now you can add or remove values from the <tt>model</tt> 
object. The <tt>model</tt> object then notifies the list of the changes, and the 
list repaints itself.</p>
<pre>model.removeElement(&quot;quick&quot;);
model.addElement(&quot;slow&quot;);
</pre>
<p class="docText">As you can see, the <tt>DefaultListModel</tt> class doesn't 
uses the same method names as the collection classes.</p>
<p class="docText">The default list model uses a vector internally to store the 
values. It inherits the list notification mechanism from <tt>AbstractListModel</tt>, 
just as the example model class of the preceding section.</p>
<div class="docNote">
  <p class="docNoteTitle">CAUTION</p>
  <table cellSpacing="0" cellPadding="1" width="90%" border="0">
    <tr>
      <td vAlign="top" width="60">
      <img alt="graphics/caution.gif" src="caution.gif" align="left" border="0" width="54" height="51"><br>
&nbsp;</td>
      <td vAlign="top">
      <p class="docText">There are <tt>JList</tt> constructors that construct a 
      list from an array or vector of objects or strings. You might think that 
      these constructors use a <tt>DefaultListModel</tt> to store these values. 
      That is not the case梩he constructors build a trivial model that can 
      access the values without any provisions for notification if the contents 
      changes. For example, here is the code for the constructor that constructs 
      a <tt>JList</tt> from a <tt>Vector</tt>:</p>
      <pre>public JList(final Vector listData)
{
   this (new AbstractListModel()
   {
      public int getSize() { return listData.size(); }
      public Object getElementAt(int i)
      { return listData.elementAt(i); }
   });
}
</pre>
      <p class="docText">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 <tt>
      final</tt> in the constructor above does not prevent you from changing the 
      vector elsewhere梚t only means that the constructor itself won't modify 
      the value of the <tt>listData</tt> reference; the keyword is required 
      because the <tt>listData</tt> object is used in the inner class.)</td>
    </tr>
  </table>
</div>
<h5 class="docSection3Title" id="ch06lev3sec5"><tt>javax.swing.JList</tt></h5>
<p><img alt="graphics/api.gif" src="api.gif" border="0" width="46" height="45"><br>
&nbsp;</p>
<ul>
  <li>
  <p class="docList"><tt>ListModel getModel()</tt></p>
  <p class="docList">gets the model of this list.</li>
</ul>
<h5 class="docSection3Title" id="ch06lev3sec6"><tt>javax.swing.DefaultListModel</tt></h5>
<p><img alt="graphics/api.gif" src="api.gif" border="0" width="46" height="45"><br>
&nbsp;</p>
<ul>
  <li>
  <p class="docList"><tt>void addElement(Object obj)</tt></p>
  <p class="docList">adds the object to the end of the model.</li>
  <li>
  <p class="docList"><tt>boolean removeElement(Object obj)</tt></p>
  <p class="docList">removes the first occurrence of the object from the model. 
  Returns <tt>true</tt> if the object was contained in the model, <tt>false</tt> 
  otherwise.</li>
</ul>
<h4 class="docSection2Title" id="ch06lev2sec4">Rendering Values</h4>
<p class="docText">So far, all lists that you saw in this chapter contained only 
strings. It is actually just as easy to show a list of icons梥imply pass an 
array or vector filled with <tt>Icon</tt> objects. More interestingly, you can 
easily represent your list values with any drawing whatsoever.</p>
<p class="docText">While the <tt>JList</tt> class can display strings and icons 
automatically, you need to install a <span class="docEmphasis">list cell 
renderer</span> into the <tt>JList</tt> object for all custom drawing. A list 
cell renderer is any class that implements the following interface:</p>
<pre>interface ListCellRenderer
{
   Component getListCellRendererComponent(JList list,
      Object value, int index,
      boolean isSelected, boolean cellHasFocus);
}
</pre>
<p class="docText">If you install a list cell renderer into a list, it gets 
called for each list value: first, if you did not select fixed-sized cells, to 
measure the size of the graphical representation of the value; then, to draw it. 
You must provide a class that returns an object of type <tt>Component</tt>, such 
that the <tt>getPreferredSize</tt> and paint methods of the returned object 
carry out these tasks as appropriate for your list values.</p>
<p class="docText">A simple way to do this is to create an inner class with 
these two methods:</p>
<pre>class MyCellRenderer implements ListCellRenderer
{
   public Component getListCellRendererComponent(final JList list,
      final Object value, final int index,
      final boolean isSelected, final boolean cellHasFocus)
   {
      return new
         JPanel()
         {
            public void paintComponent(Graphics g)
            {
               // paint code goes here
            }
            public Dimension getPreferredSize()
            {
               // size measurement code goes here
            }
         };
   }
}
</pre>
<p class="docText">In <a class="docLink" href="#ch06list03">Example 6-3</a>, we 
display the font choices graphically by showing the actual appearance of each 
font (see <a class="docLink" href="#ch06fig03">Figure 6-3</a>). In the <tt>
paintComponent</tt> 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 <tt>JList</tt> 
class. We obtain these colors by calling the <tt>getForeground</tt>/<tt>getBackground</tt> 
and <tt>getSelectionForeground</tt>/<tt>getSelectionBackground</tt> methods of 
the <tt>JList</tt> class. In the <tt>getPreferredSize</tt> method, we need to 
measure the size of the string, using the techniques that you saw in Chapter 7 
of Volume 1.</p>
<center>
<h5 id="ch06fig03" class="docFigureTitle">Figure 6-3. A list box with rendered cells</h5>
<p>
<img alt="graphics/06fig03.gif" src="06fig03.gif" border="0" width="401" height="298"></p>
</center>
<p class="docText">To install the cell renderer, simply call the <tt>
setCellRenderer</tt> method:</p>
<pre>fontList.setCellRenderer(new FontCellRenderer());
</pre>
<p class="docText">Now all list cells are drawn with the custom renderer.</p>
<p class="docText">There is actually a simpler method for writing custom 
renderers that 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 <tt>
JLabel</tt>. For example, to show the font name in its own font, we can use the 
following renderer:</p>
<pre>class FontCellRenderer implements ListCellRenderer
{
   public Component getListCellRendererComponent(JList list,
      Object value, int index, boolean isSelected,
         boolean cellHasFocus)
   {
      JLabel label = new JLabel();
      Font font = (Font)value;
      label.setText(font.getFamily());
      label.setFont(font);
      label.setOpaque(true);
      label.setBackground(isSelected
         ? list.getSelectionBackground()
         : list.getBackground());
      label.setForeground(isSelected
         ? list.getSelectionForeground()
         : list.getForeground());
      return label;
   }
}
</pre>
<p class="docText">Note that here we don't write any <tt>paintComponent</tt> or
<tt>getPreferredSize</tt> methods; the <tt>JLabel</tt> class already implements 
these methods to our satisfac-tion. All we need to do is to configure the label 
appropriately by setting its text, font, and color.</p>
<p class="docText">For added conciseness, the <tt>FontCellRenderer</tt> can even 
extend <tt>JLabel</tt>, configure <span class="docEmphasis">itself</span> with 
every call to <tt>getListCellRendererComponent</tt>, and then return <tt>this</tt>:</p>
<pre>class FontCellRenderer extends JLabel implements ListCellRenderer
{
   public Component getListCellRendererComponent(JList list,
      Object value, int index, boolean isSelected,
         boolean cellHasFocus)
   {
      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;
   }
}
</pre>
<p class="docText">This code is a convenient shortcut for those cases where an 
existing component梚n this case, <tt>JLabel</tt>梐lready provides all 
functionality that is needed to render a cell value.</p>
<h5 id="ch06list03" class="docExampleTitle">Example 6-3 ListRenderingTest.java</h5>
<pre>  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.show();
 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(&quot;ListRenderingTest&quot;);
 30.       setSize(WIDTH, HEIGHT);
 31.
 32.       ArrayList fonts = new ArrayList();
 33.       final int SIZE = 24;
 34.       fonts.add(new Font(&quot;Serif&quot;, Font.PLAIN, SIZE));
 35.       fonts.add(new Font(&quot;SansSerif&quot;, Font.PLAIN, SIZE));
 36.       fonts.add(new Font(&quot;Monospaced&quot;, Font.PLAIN, SIZE));
 37.       fonts.add(new Font(&quot;Dialog&quot;, Font.PLAIN, SIZE));
 38.       fonts.add(new Font(&quot;DialogInput&quot;, Font.PLAIN, SIZE));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?