_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>
</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("quick");
values.addElement("brown");
. . .
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>
</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("quick");
model.addElement("brown");
. . .
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("quick");
model.addElement("slow");
</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>
</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>
</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>
</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("ListRenderingTest");
30. setSize(WIDTH, HEIGHT);
31.
32. ArrayList fonts = new ArrayList();
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));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?