epubjs
Version:
Render ePub documents in the browser, across many devices
407 lines • 74.3 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Components</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Components"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-16-SECT-1"/>Components</h1></div></div></div><p>A <span class="emphasis"><em>component</em></span> is the fundamental user interface
object in Java. Everything you see on the display in a Java application is
a component. This includes things like windows, panels, buttons,
checkboxes, scrollbars, lists, menus, and text fields. To be used, a
component usually must be placed in a <span class="emphasis"><em>container</em></span>.
Container objects group components, arrange them for display using a
layout manager, and associate them with a particular display device. All
Swing components are derived from the abstract <a id="I_indexterm16_id784966" class="indexterm"/><code class="literal">javax.swing.JComponent</code>
class, as you saw in <a class="xref" href="ch16.html#learnjava3-CHP-16-FIG-1" title="Figure 16-1. User interface components in the javax.swing package">Figure 16-1</a>. For
example, the <a id="I_indexterm16_id784982" class="indexterm"/><code class="literal">JButton</code> class is a
subclass of <a id="I_indexterm16_id784992" class="indexterm"/><code class="literal">AbstractButton</code>, which is
itself a subclass of the <code class="literal">JComponent</code>
class.</p><p><code class="literal">JComponent</code> is the root of the
Swing component hierarchy, but it descends from the AWT <a id="I_indexterm16_id785016" class="indexterm"/><code class="literal">Container</code> class. At this
bottom level, Swing is based on AWT, so our conversation occasionally
delves into the AWT package. <code class="literal">Container</code>’s superclass is <code class="literal">Component</code>, the root of all AWT components, and
<code class="literal">Component</code>’s superclass is, finally,
<code class="literal">Object</code>. Because <code class="literal">JComponent</code> inherits from <code class="literal">Container</code>, it has the capabilities of both a
component and a container.</p><p>AWT and Swing, then, have parallel hierarchies. The root of AWT’s
hierarchy is <code class="literal">Component</code>, while Swing’s
components are based on <code class="literal">JComponent</code>.
You’ll find similar classes in both hierarchies, such as <code class="literal">Button</code> and <code class="literal">JButton</code>, <code class="literal">List</code>, and <code class="literal">JList</code>. But Swing is much more than a replacement
for AWT—it contains sophisticated components as well as a real
implementation of the Model-View-Controller (MVC) paradigm, which we’ll
discuss later.</p><p>For the sake of simplicity, we can split the functionality of the
<code class="literal">JComponent</code> class into two categories:
appearance and behavior. The <code class="literal">JComponent</code>
class contains methods and variables that control an object’s general
appearance. This includes basic attributes, such as its visibility, its
current size and location, and certain common graphical defaults, such as
font and background color, used by different subclasses in different ways.
The <code class="literal">JComponent</code> class also contains graphics
and event-handling methods, which are overridden by subclasses to produce
all of the different kinds of widgets that we will see.</p><p>When a component is first displayed, it’s associated with a
particular display device. The <code class="literal">JComponent</code> class encapsulates access to its
display area on that device. It includes tools for rendering graphics, for
working with off-screen resources, and for receiving user input. Under the
covers, <code class="literal">JComponent</code> makes heavy use of
the Java 2D API to handle things like font smoothing, rendering
optimizations, and rendering hints. With recent versions of Java (6 and
later), rendering speed and quality are often indistinguishable from
native applications on popular operating systems.</p><p>When we talk about a component’s behavior, we mean the way it
responds to user-driven events. When the user performs an action (such as
pressing the mouse button) within a component’s display area, a Swing
thread delivers an event object that describes what happened. The event is
delivered to objects that have registered themselves as listeners for that
type of event from that component. For example, when the user clicks on a
button, the button generates an <a id="I_indexterm16_id785158" class="indexterm"/><code class="literal">ActionEvent</code> object. To
receive those events, an object registers with the button as an <a id="I_indexterm16_id785169" class="indexterm"/><code class="literal">ActionListener</code>.</p><p>Events are delivered by invoking designated event handler methods
within the receiving object (the “listener”). A listener object receives
specific types of events through methods of its listener interfaces (for
example, through the <code class="literal">actionPerformed()</code>
method of the <code class="literal">ActionListener</code> interface)
for the types of events in which it is interested. Specific types of
events cover different categories of component user interaction. For
example, <a id="I_indexterm16_id785199" class="indexterm"/><code class="literal">Mouse</code><code class="literal">Event</code>s describe activities of the mouse
within a component’s area, <a id="I_indexterm16_id785219" class="indexterm"/><code class="literal">KeyEvent</code>s describe
keypresses, and higher-level events (such as <code class="literal">ActionEvent</code>s) indicate that a user interface
component has done its job.</p><p>We will describe events thoroughly in this chapter because they are
so fundamental to the way in which user interfaces function in Java. But
they aren’t limited to building user interfaces; they are an important
interobject communications mechanism, which may be used by completely
nongraphical parts of an application, as well. They are particularly
important in the context of JavaBeans, which uses events as a generalized
change-notification mechanism.</p><p>Swing’s event architecture is very flexible. Instead of requiring
every component to listen for and handle events for its own bit of the
user interface, an application may register arbitrary event “handler”
objects to receive the events for one or more components and “glue” those
events to the correct application logic. A container might, for example,
process some of the events relating to its child components.</p><p>In the graphical realm, the primary responsibility of a container is
to lay out the components it contains visually, within its borders. A
component informs its container when it does something that might affect
other components in the container, such as changing its size or
visibility. The container then tells its layout manager that it is time to
rearrange the child components.</p><p>As we mentioned, Swing components are all fundamentally derived from
<code class="literal">Container</code>. This doesn’t mean that all
Swing components can meaningfully contain arbitrary GUI elements within
themselves. It does mean that the container-component relationship is
built in at a low level. Containers can manage and arrange <code class="literal">JComponent</code> objects without knowing what they are
or what they are doing. Components can be swapped and replaced with new
versions easily and combined into composite user interface objects that
can be treated as individual components themselves. This lends itself well
to building larger, reusable user interface items.</p><div class="sect2" title="Peers and Look-and-Feel"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.1"/>Peers and Look-and-Feel</h2></div></div></div><p><a id="idx10922" class="indexterm"/> <a id="idx10941" class="indexterm"/> <a id="idx10946" class="indexterm"/> <a id="idx10963" class="indexterm"/>Swing components are sometimes referred to as
<span class="emphasis"><em>peerless</em></span>, or <span class="emphasis"><em>lightweight</em></span>.
These terms refer to the relationship that AWT has (and Swing does not
have, respectively) with the native toolkits for rendering components on
each platform. To get native components on the screen, AWT utilizes a
set of peer objects that bridge the gap from pure Java to the host
operating system.</p><p>At some level, of course, all our components have to talk to
objects that contain native methods to interact with the host operating
environment; the difference is at what level this occurs. AWT uses a set
of peer interfaces. The peer interface makes it possible for a pure
Java-language graphic component to use a corresponding real
component—the peer object—in the native environment. With AWT, you don’t
generally deal directly with peer interfaces or the objects behind them;
peer handling is encapsulated within the <code class="literal">Component</code> class.</p><p>AWT relies heavily on peers. For example, if you create a window
and add eight buttons to it, AWT creates nine peers for you—one for the
window and one for each of the buttons. As an application programmer,
you don’t have to worry about the peers, but they are always lurking
under the surface, doing the real work of interacting with the operating
system’s windowing toolkit.</p><p>In Swing, by contrast, most components are
<span class="emphasis"><em>peerless</em></span>, or <span class="emphasis"><em>lightweight</em></span>. This
means that Swing components don’t have any direct interaction with the
underlying windowing system. They draw themselves in their parent
container and respond to user events in pure Java, with no native code
involved. In Swing, only the top-level (lowest API level) windows
interact with the windowing system. These Swing containers descend from
AWT counterparts, and, thus, still have peers. In Swing, if you create a
window and add eight buttons to it, only one peer is created—for the
window. Because it has fewer interactions with the underlying windowing
system than AWT, Swing is less vulnerable to the peculiarities of any
particular platform.</p><p>With lightweight components, it is easy to change their
appearance. Because each component draws itself instead of relying on a
peer, it can decide at runtime how to render itself. Accordingly, Swing
supports different <a id="I_indexterm16_id785396" class="indexterm"/><a id="I_indexterm16_id785404" class="indexterm"/><a id="I_indexterm16_id785410" class="indexterm"/><span class="emphasis"><em>look-and-feel</em></span> schemes, which can be
changed at runtime. (A look-and-feel is the collected appearance of
components in an application.) Look-and-feels based on Windows,
Macintosh, and Motif are available (though licensing issues may encumber
their use on various platforms), as well as several entirely original
Java creations, including Metal, Synth and Nimbus. Metal is the default
cross-platform look-and-feel. It has a flat minimalist aesthetic and is
very functional but, at this point, appears dated when compared to
current versions of popular desktop environments. Synth makes Java
applications “skinnable” at a high level using an XML descriptor file
and images as resources. Java SE 6 update 10 introduced Nimbus, the
first Java look-and-feel that is aesthetically on par with modern
desktop operating systems such as OS X and Windows. Nimbus is
vector-based, which allows components to be smoothly scaled for use on
the new generation of high-density displays. If you want a consistent
cross-platform look-and-feel, Nimbus is the best option.<a id="I_indexterm16_id785438" class="indexterm"/><a id="I_indexterm16_id785445" class="indexterm"/><a id="I_indexterm16_id785452" class="indexterm"/><a id="I_indexterm16_id785460" class="indexterm"/></p></div><div class="sect2" title="The MVC Framework"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.2"/>The MVC Framework</h2></div></div></div><p><a id="idx10920" class="indexterm"/> <a id="idx10944" class="indexterm"/> <a id="idx10961" class="indexterm"/>Before continuing our discussion of GUI concepts, we want
to make a brief aside and talk about the MVC framework. As we’ve
discussed, MVC is a method of building reusable components that
logically separates the structure, presentation, and behavior of a
component into separate pieces. MVC is primarily concerned with building
user interface components, but the basic ideas can be applied to many
design issues; its principles can be seen throughout Java.</p><p>The fundamental idea behind MVC is the separation of the data
model for an item from its presentation. For example, we can draw
different representations of the data in a spreadsheet (e.g., bar
graphs, pie charts). The data is the <a id="I_indexterm16_id785522" class="indexterm"/><a id="I_indexterm16_id785528" class="indexterm"/><span class="emphasis"><em>model</em></span>; the particular representation
is the <a id="I_indexterm16_id785537" class="indexterm"/><a id="I_indexterm16_id785542" class="indexterm"/><span class="emphasis"><em>view</em></span>. A single model can have many
views that present the data differently. A user interface component’s
<a id="I_indexterm16_id785553" class="indexterm"/><a id="I_indexterm16_id785559" class="indexterm"/><span class="emphasis"><em>controller</em></span> defines and governs its
behavior. Typically, this includes changes to the model, which, in turn,
cause the view(s) to change. For a checkbox component, the data model
could be a single Boolean variable, indicating whether it’s checked or
not. The behavior for handling mouse-click events would alter the model,
and the view would examine that data when it draws the on-screen representation.</p><p>The way in which Swing objects communicate, by passing events from
sources to listeners, is part of this MVC concept of separation. Event
listeners are “observers” (controllers) and event sources are
“observables” (models).<sup>[<a id="learnjava3-CHP-16-FN-2" href="#ftn.learnjava3-CHP-16-FN-2" class="footnote">38</a>]</sup> When an observable changes or performs a function, it
notifies all its observers of the activity.</p><p>Swing components explicitly support MVC. Each component is
actually composed of two pieces. One piece, called the UI-delegate, is
responsible for the “view” and “controller” roles. It takes care of
drawing the component and responding to user events. The second piece is
the data model itself. This separation makes it possible for multiple
Swing components to share a single data model. For example, a read-only
text box and a drop-down list box could use the same list of strings as
a data model.<a id="I_indexterm16_id785640" class="indexterm"/><a id="I_indexterm16_id785647" class="indexterm"/><a id="I_indexterm16_id785654" class="indexterm"/></p></div><div class="sect2" title="Painting"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.3"/>Painting</h2></div></div></div><p><a id="idx10921" class="indexterm"/> <a id="idx10945" class="indexterm"/> <a id="idx10962" class="indexterm"/>In an event-driven environment such as Swing, components
can be asked to draw themselves at any time. In a more procedural
programming environment, you might expect a component to be involved in
drawing only when first created or when it changes its appearance. In
Java, however, components act in a way that is closely tied to the
underlying behavior of the display environment. For example, when you
obscure a component with another window and then reexpose it, a Swing
thread may ask the component to redraw itself.</p><p>Swing asks a component to draw itself by calling its <a id="I_indexterm16_id785712" class="indexterm"/><code class="literal">paint()</code> method.
<code class="literal">paint()</code> may be called at any time,
but in practice, it’s called when the object is first made visible,
whenever it changes its appearance, or whenever some tragedy in the
display system messes up its area. Because <code class="literal">paint()</code> can’t generally make any assumptions
about why it was called, it must redraw the component’s entire display.
The system may limit the drawing if only part of the component needs to
be redrawn, but you don’t have to worry about this. Swing is fairly
smart and will do everything it can to avoid asking components to redraw
themselves (including using “backing store” where applicable).</p><p>A component never calls its <code class="literal">paint()</code> method directly. Instead, if a
component requires redrawing, it requests a call to <code class="literal">paint()</code> by invoking <a id="I_indexterm16_id785760" class="indexterm"/><code class="literal">repaint()</code>. The <code class="literal">repaint()</code> method asks Swing to schedule the
component for repainting. At some point after that, a call to <code class="literal">paint()</code> occurs. Swing is allowed to manage
these requests in whatever way is most efficient. If there are too many
requests to handle, or if there are multiple requests for the same
component, the thread can collapse a number of repaint requests into a
single call to <code class="literal">paint()</code>. This means
that you don’t normally know exactly when <code class="literal">paint()</code> is called in response to a <code class="literal">repaint()</code>; all you can expect is that it
happens at least once, after you request it.</p><p>Calling <code class="literal">repaint()</code> is normally
an implicit request to be updated as soon as possible. Another form of
<code class="literal">repaint()</code> allows you to specify a
time period within which you would like an update, giving the system
more flexibility in scheduling the request. The system tries to repaint
the component within the time you specify, but if you happen to make
more than one repaint request within that time period, the system may
simply condense them to carry out a single update within the time you
specified. An application performing simple animation could use this
method to govern its refresh rate (by specifying a period that is the
inverse of the desired frame rate).</p><p>As we’ve mentioned, Swing components can act as containers holding
other components. Because every Swing component does its own drawing,
Swing components are responsible for telling any contained components to
draw themselves. Fortunately, this is all taken care of for you by a
component’s default <code class="literal">paint()</code> method.
If you override this method, however, you have to make sure to call the
superclass’s implementation like this:</p><a id="I_16_tt977"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">paint</code><code class="o">(</code><code class="n">Graphics</code> <code class="n">g</code><code class="o">)</code> <code class="o">{</code>
<code class="kd">super</code><code class="o">.</code><code class="na">paint</code><code class="o">(</code><code class="n">g</code><code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>There’s a cleaner way around this problem. All Swing components
have a method called <a id="I_indexterm16_id785849" class="indexterm"/><code class="literal">paintComponent()</code>. While
<code class="literal">paint()</code> is responsible for drawing
the component as well as its contained components, <code class="literal">paintComponent()</code>’s sole responsibility is
drawing the component itself. If you override <code class="literal">paintComponent()</code> instead of <code class="literal">paint()</code>, you won’t have to worry about drawing
contained components.</p><p>Both <code class="literal">paint()</code> and <code class="literal">paintComponent()</code> receive a single argument: a
<code class="literal">Graphics</code> object. The <code class="literal">Graphics</code> object represents the component’s
graphics context. It corresponds to the area of the screen on which the
component can draw and provides the methods for performing primitive
drawing and image manipulation. (We’ll look at the <code class="literal">Graphics</code> class in detail in <a class="xref" href="ch18.html" title="Chapter 18. More Swing Components">Chapter 18</a>.)<a id="I_indexterm16_id785922" class="indexterm"/><a id="I_indexterm16_id785929" class="indexterm"/><a id="I_indexterm16_id785936" class="indexterm"/></p></div><div class="sect2" title="Enabling and Disabling Components"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.4"/>Enabling and Disabling Components</h2></div></div></div><p><a id="idx10916" class="indexterm"/> <a id="idx10926" class="indexterm"/> <a id="idx10929" class="indexterm"/> <a id="idx10955" class="indexterm"/>Standard Swing components can be turned on and off by
calling the <a id="I_indexterm16_id786000" class="indexterm"/><code class="literal">setEnabled()</code> method.
When a component such as a <a id="I_indexterm16_id786011" class="indexterm"/><code class="literal">JButton</code> or <a id="I_indexterm16_id786021" class="indexterm"/><code class="literal">JTextField</code> is disabled,
it becomes “ghosted” or “greyed out” and doesn’t respond to user
input.</p><p>For example, let’s see how to create a component that can be used
only once. This requires getting ahead of the story; we won’t explain
some aspects of this example until later. Earlier, we said that a
<code class="literal">JButton</code> generates an <code class="literal">ActionEvent</code> when it is pressed. This event is
delivered to the listeners’ <code class="literal">actionPerformed()</code> method. The following code
disables the component that generated the event:</p><a id="I_16_tt978"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">boolean</code> <code class="kt">void</code> <code class="nf">actionPerformed</code><code class="o">(</code><code class="n">ActionEvent</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">((</code><code class="n">JComponent</code><code class="o">)</code><code class="n">e</code><code class="o">.</code><code class="na">getSource</code><code class="o">()).</code><code class="na">setEnabled</code><code class="o">(</code><code class="kc">false</code><code class="o">);</code>
<code class="o">}</code></pre><p>This code calls <a id="I_indexterm16_id786069" class="indexterm"/><code class="literal">getSource()</code> to find out
which component generated the event. We cast the result to <code class="literal">JComponent</code> because we don’t necessarily know
what kind of component we’re dealing with; it might not be a button,
because other kinds of components can generate action events. Once we
know which component generated the event, we disable it.</p><p>You can also disable an entire container. Disabling a <code class="literal">JPanel</code>, for instance, disables all the
components it contains.<a id="I_indexterm16_id786103" class="indexterm"/><a id="I_indexterm16_id786110" class="indexterm"/><a id="I_indexterm16_id786117" class="indexterm"/><a id="I_indexterm16_id786124" class="indexterm"/></p></div><div class="sect2" title="Focus, Please"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.5"/>Focus, Please</h2></div></div></div><p><a id="idx10917" class="indexterm"/> <a id="idx10936" class="indexterm"/> <a id="idx10956" class="indexterm"/>In order to receive keyboard events, a component has to
have keyboard <span class="emphasis"><em>focus</em></span>. The component with the focus
is the currently <span class="emphasis"><em>selected</em></span> component on the screen
and is usually highlighted visually. It receives all keyboard event
information until the focus changes to a new component. Typically, a
component receives focus when the user clicks on it with the mouse or
navigates to it using the keyboard. A component can ask for focus with
the <code class="literal">JComponent</code> ’s <a id="I_indexterm16_id786193" class="indexterm"/><code class="literal">requestFocus()</code> method.
You can configure whether a given component is eligible to receive focus
with the <a id="I_indexterm16_id786205" class="indexterm"/><code class="literal">setFocusable()</code> method.
By default, most components, including things such as buttons and
checkboxes, are “focusable.” To make an entire window and its components
nonfocusable, use the <code class="literal">Window
setFocusableWindowState()</code> method.</p><p>The control of focus is often at the heart of the user’s
experience with an application. Especially with text entry fields and
forms, users are accustomed to a smooth transfer of focus with the use
of keyboard navigation cues (e.g., Tab and Shift-Tab for forward and
backward field navigation). The management of focus in a large GUI with
many components could be complex. Fortunately, in Java 1.4 and later,
Swing handles almost all this behavior for you, so, in general, you
don’t have to implement code to specify how focus is transferred. Java
1.4 introduced an entirely new focus subsystem. The flexible <code class="literal">KeyboardFocusManager</code> API provides the expected
common behavior by default and allows customization via <code class="literal">FocusTraversalPolicy</code> objects. We’ll discuss
focus-related events later in this chapter and focus navigation more in
<a class="xref" href="ch18.html" title="Chapter 18. More Swing Components">Chapter 18</a>.<a id="I_indexterm16_id786251" class="indexterm"/></p></div><div class="sect2" title="Other Component Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.6"/>Other Component Methods</h2></div></div></div><p>The <code class="literal">JComponent</code> class is very
large; it has to provide the base-level functionality for all the
various kinds of Java GUI objects. It inherits a lot of functionality
from its parent <code class="literal">Container</code> and
<code class="literal">Component</code> classes. We don’t have room
to document every method of the <code class="literal">JComponent</code> class here, but we’ll flesh out our
discussion by covering some of the more important ones:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">Container
getParent()</code><br/></span><span class="term"><code class="literal">String getName()<a id="I_indexterm16_id786305" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setName(String
name)</code></span></dt><dd><p><a id="I_indexterm16_id786318" class="indexterm"/>Get or assign the <code class="literal">String</code> name of this component. Naming a
component is useful for debugging. The name is returned by
<code class="literal">toString()</code>.</p></dd><dt><span class="term"><code class="literal">void setVisible(boolean
visible)</code></span></dt><dd><p><a id="I_indexterm16_id786345" class="indexterm"/>Make the component visible or invisible within its
container. If you change the component’s visibility, the
container’s layout manager automatically lays out its visible
components.</p></dd><dt><span class="term"><code class="literal">Color getForeground()<a id="I_indexterm16_id786362" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setForeground(Color c)<a id="I_indexterm16_id786373" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setBackground(Color c)<a id="I_indexterm16_id786384" class="indexterm"/></code><br/></span><span class="term"><code class="literal">Color
getBackground()</code></span></dt><dd><p><a id="I_indexterm16_id786398" class="indexterm"/>Get and set the foreground and background colors for
this component. The foreground color of any component is the
default color used for drawing. For example, it is the color used
for text in a text field as well as the default drawing color for
the <code class="literal">Graphics</code> object passed to
the component’s <code class="literal">paint()</code> and
<code class="literal">paintComponent()</code> methods. The
background color is used to fill the component’s area when it is
cleared by the default implementation of <code class="literal">update()</code>.</p></dd><dt><span class="term"><code class="literal">Dimension getSize()<a id="I_indexterm16_id786438" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setSize(int width, int
height)</code></span></dt><dd><p><a id="I_indexterm16_id786451" class="indexterm"/>Get and set the current size of the component. Note
that a layout manager may change the size of a component even
after you’ve set its size yourself. To change the size a component
“wants” to be, use <code class="literal">setPreferredSize()</code>. There are other
methods in <code class="literal">JComponent</code> to set
its location, but this is normally the job of a layout
manager.</p></dd><dt><span class="term"><code class="literal">Dimension
getPreferredSize()<a id="I_indexterm16_id786481" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setPreferredSize(Dimension
preferredSize)</code></span></dt><dd><p><a id="I_indexterm16_id786494" class="indexterm"/>Use these methods to examine or set the preferred
size of a component. Layout managers attempt to set components to
their preferred sizes. If you change a component’s preferred size,
you must call the method <code class="literal">revalidate()</code> on the component to get it
laid out again.</p></dd><dt><span class="term"><code class="literal">Cursor getCursor()<a id="I_indexterm16_id786518" class="indexterm"/></code><br/></span><span class="term"><code class="literal">void setCursor(Cursor
cursor)</code></span></dt><dd><p><a id="I_indexterm16_id786531" class="indexterm"/>Get or set the type of cursor (mouse pointer) used
when the mouse is over this component’s area. For example:</p></dd></dl></div><a id="I_16_tt979"/><pre class="programlisting"> <code class="n">JComponent</code> <code class="n">myComponent</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">Cursor</code> <code class="n">crossHairs</code> <code class="o">=</code>
<code class="n">Cursor</code><code class="o">.</code><code class="na">getPredefinedCursor</code><code class="o">(</code> <code class="n">Cursor</code><code class="o">.</code><code class="na">CROSSHAIR_CURSOR</code> <code class="o">);</code>
<code class="n">myComponent</code><code class="o">.</code><code class="na">setCursor</code><code class="o">(</code> <code class="n">crossHairs</code> <code class="o">);</code></pre><div class="sect3" title="Containers"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-16-SECT-1.6.1"/>Containers</h3></div></div></div><p>A container is a kind of component that holds and manages other
components. Three of the most useful general container types are
<a id="I_indexterm16_id786558" class="indexterm"/><code class="literal">JFrame</code>, <a id="I_indexterm16_id786569" class="indexterm"/><code class="literal">JPanel</code>, and
<a id="I_indexterm16_id786579" class="indexterm"/><code class="literal">JApplet</code>. A <code class="literal">JFrame</code> is a top-level window on your
display. <code class="literal">JFrame</code> is derived from
<code class="literal">java.awt.Window</code>, which is pretty
much the same but lacks a border (<a id="I_indexterm16_id786607" class="indexterm"/><code class="literal">JWindow</code> is the swing
version of <code class="literal">Window</code>). A <code class="literal">JPanel</code> is a generic container element that
groups components inside <code class="literal">JFrame</code>s
and other <code class="literal">JPanel</code>s. The <code class="literal">JApplet</code> class is a kind of container that
provides the foundation for applets that run inside web browsers. Like
other containers, a <code class="literal">JApplet</code> can
hold other user-interface components. You can also use the <code class="literal">JComponent</code> class directly, like a <code class="literal">JPanel</code>, to hold components inside another
container. With the exception of <code class="literal">JFrame</code>, <code class="literal">JWindow</code>, <code class="literal">JApplet</code>, and <a id="I_indexterm16_id786679" class="indexterm"/><code class="literal">JDialog</code> (another
window-like container), which are derived from AWT components, all the
components and containers in Swing are lightweight.</p><p>A container maintains the list of “child” components it manages
and has methods for dealing with those components. Note that this
child relationship refers to a visual hierarchy, not a subclass/superclass
hierarchy. By themselves, most components aren’t very useful until
they are added to a container and displayed. The <code class="literal">add()</code> method of the <code class="literal">Container</code> class adds a component to the
container. Thereafter, this component can be displayed in the
container’s display area and positioned by its layout manager. You can
remove a component from a container with the <code class="literal">remove()</code> method.</p></div></div><div class="sect2" title="Layout Managers"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.7"/>Layout Managers</h2></div></div></div><p><a id="idx10919" class="indexterm"/> <a id="idx10959" class="indexterm"/>A <span class="emphasis"><em>layout manager</em></span> is an object that
controls the placement and sizing of components within the display area
of a container. A layout manager is like a window manager in a display
system; it controls where the components go and how big they are. Every
container has a default layout manager, but you can install a new one by
calling the container’s <a id="I_indexterm16_id786767" class="indexterm"/><code class="literal">setLayout()</code>
method.</p><p>Swing comes with a few layout managers that implement common
layout schemes. The default layout manager for a <a id="I_indexterm16_id786780" class="indexterm"/><code class="literal">JPanel</code> is a <a id="I_indexterm16_id786791" class="indexterm"/><code class="literal">FlowLayout</code>, which tries
to place objects at their preferred size from left to right and top to
bottom in the container. The default for a <code class="literal">JFrame</code> is a <a id="I_indexterm16_id786808" class="indexterm"/><code class="literal">BorderLayout</code>, which
places objects at specific locations within the window, such as <code class="literal">NORTH</code>, <code class="literal">SOUTH</code>, and <code class="literal">CENTER</code>. Another layout manager, <a id="I_indexterm16_id786836" class="indexterm"/><code class="literal">GridLayout</code>, arranges
components in a rectangular grid. The most general (and difficult to
use) layout manager is <a id="I_indexterm16_id786847" class="indexterm"/><code class="literal">GridBagLayout</code>, which
lets you do the kinds of things you can do with HTML tables. (We’ll get
into the details of all these layout managers in <a class="xref" href="ch19.html" title="Chapter 19. Layout Managers">Chapter 19</a>.)</p><p>When you add a component to a container using a simple layout
manager, you’ll often use the version of <code class="literal">add()</code> that takes a single <code class="literal">Component</code> as an argument. However, if you’re
using a layout manager that uses “constraints,” such as <code class="literal">BorderLayout</code> or <code class="literal">GridBagLayout</code>, you must specify additional
information about where to put the new component. For that, you can use
the version that takes a constraint object. Here’s how to place a
component at the top edge of a container that uses a <code class="literal">BorderLayout</code> manager:</p><a id="I_16_tt980"/><pre class="programlisting"> <code class="n">myContainer</code><code class="o">.</code><code class="na">add</code><code class="o">(</code><code class="n">myComponent</code><code class="o">,</code> <code class="n">BorderLayout</code><code class="o">.</code><code class="na">NORTH</code><code class="o">);</code></pre><p>In this case, the constraint object is the static member variable
<code class="literal">NORTH</code>. <code class="literal">GridBagLayout</code> uses a much more complex
constraint object to specify positioning.<a id="I_indexterm16_id786924" class="indexterm"/><a id="I_indexterm16_id786931" class="indexterm"/></p></div><div class="sect2" title="Insets"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.8"/>Insets</h2></div></div></div><p><a id="I_indexterm16_id786945" class="indexterm"/> <a id="idx10939" class="indexterm"/> <a id="idx10958" class="indexterm"/>Insets specify a container’s margins; the space specified
by the container’s insets won’t be used by a layout manager. Insets are
described by an <a id="I_indexterm16_id786981" class="indexterm"/><code class="literal">Insets</code> object, which
has four public <code class="literal">int</code> fields:
<a id="I_indexterm16_id786997" class="indexterm"/><code class="literal">top</code>, <a id="I_indexterm16_id787007" class="indexterm"/><code class="literal">bottom</code>, <a id="I_indexterm16_id787018" class="indexterm"/><code class="literal">left</code>, and <a id="I_indexterm16_id787028" class="indexterm"/><code class="literal">right</code>. You normally
don’t need to worry about the insets; the container sets them
automatically, taking into account extras like the menu bar that may
appear at the top of a frame. To find the insets, call the component’s
<a id="I_indexterm16_id787043" class="indexterm"/><code class="literal">getInsets()</code> method,
which returns an <code class="literal">Insets</code>
object.<a id="I_indexterm16_id787059" class="indexterm"/><a id="I_indexterm16_id787066" class="indexterm"/></p></div><div class="sect2" title="Z-Ordering (Stacking Components)"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.9"/>Z-Ordering (Stacking Components)</h2></div></div></div><p><a id="I_indexterm16_id787080" class="indexterm"/> <a id="I_indexterm16_id787089" class="indexterm"/> <a id="I_indexterm16_id787096" class="indexterm"/> <a id="I_indexterm16_id787106" class="indexterm"/>With the standard layout managers, components are not
allowed to overlap. However, if you use custom-built layout managers or
absolute positioning, components within a container may overlap. If they
do, the order in which components were added to a container matters.
When components overlap, they are “stacked” in the order in which they
were added: the first component added to the container is on top, and
the last is on the bottom. To give you more control over stacking, two
additional forms of the <code class="literal">add()</code> method
take an extra integer argument that lets you specify the component’s
exact position in the container’s stacking order. Again, you don’t
normally need to think about this, but it’s nice to know for the sake of
completeness that it’s there.</p></div><div class="sect2" title="The revalidate() and doLayout() Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.10"/>The revalidate() and doLayout() Methods</h2></div></div></div><p><a id="idx10915" class="indexterm"/> <a id="idx10923" class="indexterm"/> <a id="idx10927" class="indexterm"/> <a id="idx10948" class="indexterm"/> <a id="idx10954" class="indexterm"/> <a id="idx10964" class="indexterm"/>A layout manager arranges the components in a container
only when it is asked to do so. Several things can mess up a container
after it’s initially laid out:</p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>Changing its size</p></li><li class="listitem"><p>Resizing or moving one of its child components</p></li><li class="listitem"><p>Adding, showing, removing, or hiding a child component</p></li></ul></div><p>Any of these actions cause the container to be marked
<span class="emphasis"><em>invalid</em></span>. This means that it needs to have its child
components readjusted by its layout manager. In most cases, Swing
readjusts the layout automatically. All components, not just containers,
maintain a notion of when they are valid or invalid. If the size,
location, or internal layout of a Swing component changes, its <code class="literal">revalidate()</code> method is automatically called.
Internally, the <code class="literal">revalidate()</code> method
first calls the method <code class="literal">invalidate()</code>
to mark the component and all its enclosing containers as invalid. It
then validates the tree. Validation descends the hierarchy, starting at
the nearest <span class="emphasis"><em>validation root</em></span> container, recursively
validating each child. Validating a child <code class="literal">Container</code> means invoking its <code class="literal">doLayout()</code> method, which asks the layout
manager to do its job and then notes that the <code class="literal">Container</code> has been reorganized by setting its
state to valid again. A validation root is a container that can
accommodate children of any size such as <code class="literal">JScrollPane</code> (and, hence, can accommodate any
possible changes in its child hierarchy without upsetting its own
parents).</p><p>There are a few cases in which you may need to tell Swing to fix
things manually. One example is when you change the preferred size of a
component (as opposed to its actual onscreen size). To clean up the
layout, call the <code class="literal">revalidate()</code> method.
For example, if you have a small <code class="literal">JPanel</code>—say, a keypad holding some buttons—and
you change the preferred size of the <code class="literal">JPanel</code> by calling its <code class="literal">setPreferredSize()</code> method, you should also
call <code class="literal">revalidate()</code> on the panel or its
immediate container. The layout manager of the panel then rearranges its
buttons to fit inside its new area.<a id="I_indexterm16_id787320" class="indexterm"/><a id="I_indexterm16_id787327" class="indexterm"/><a id="I_indexterm16_id787334" class="indexterm"/><a id="I_indexterm16_id787341" class="indexterm"/><a id="I_indexterm16_id787348" class="indexterm"/><a id="I_indexterm16_id787355" class="indexterm"/></p></div><div class="sect2" title="Managing Components"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.11"/>Managing Components</h2></div></div></div><p><a id="I_indexterm16_id787369" class="indexterm"/> <a id="I_indexterm16_id787377" class="indexterm"/>There are a few additional tools of the <code class="literal">Container</code> class we should mention:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">Component[]
getComponents()</code></span></dt><dd><p><a id="I_indexterm16_id787404" class="indexterm"/>Returns the container’s components in an
array.</p></dd><dt><span class="term"><code class="literal">void list(PrintWriter out, int
indent)</code></span></dt><dd><p><a id="I_indexterm16_id787421" class="indexterm"/>Generates a list of the components in this container
and writes them to the specified <code class="literal">PrintWriter</code>.</p></dd><dt><span class="term"><code class="literal">Component getComponentAt(int x, int
y)</code></span></dt><dd><p><a id="I_indexterm16_id787444" class="indexterm"/>Tells you what component is at the specified
coordinates in the container’s coordinate system.</p></dd></dl></div></div><div class="sect2" title="Listening for Components"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.12"/>Listening for Components</h2></div></div></div><p><a id="I_indexterm16_id787460" class="indexterm"/> <a id="I_indexterm16_id787468" class="indexterm"/> <a id="idx10960" class="indexterm"/>You can use the <a id="I_indexterm16_id787490" class="indexterm"/><code class="literal">ContainerListener</code>
interface to automate setting up a container’s new components. A
container that implements this interface can receive an event whenever
it gains or loses a component. This facility makes it easy for a
container to micromanage its components.<a id="I_indexterm16_id787505" class="indexterm"/></p></div><div class="sect2" title="Windows, Frames and Splash Screens"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-16-SECT-1.13"/>Windows, Frames and Splash Screens</h2></div></div></div><p><a id="idx10918" class="indexterm"/> <a id="idx10924" class="indexterm"/> <a id="idx10938" class="indexterm"/> <a id="idx10950" class="indexterm"/> <a id="idx10957" class="indexterm"/> <a id="idx10965" class="indexterm"/>Windows and frames are the top-level containers for Java
components. A <a id="I_indexterm16_id787595" class="indexterm"/><code class="literal">JWindow</code> is simply a
plain, graphical screen that displays in your windowing system. Windows
have no frills; they are mainly suitable for pop-up windows and in
situations where drop-down components such as menus and combo boxes
extend outside their parent frame. <a id="I_indexterm16_id787607" class="indexterm"/><code class="literal">JFrame</code>, on the other
hand, is a subclass of <code class="literal">JWindow</code> that
has a titlebar, window-managed buttons (close, minimize, etc.), and
border. You can drag a frame around on the screen and resize it, using
the ordinary controls for your windowing environment. <a class="xref" href="ch16s01.html#learnjava3-CHP-16-FIG-2" title="Figure 16-2. A frame and a window">Figure 16-2</a> shows a <code class="literal">JFrame</code> on the left and a <code class="literal">JWindow</code> on the right.</p><p>All other Swing components and containers must be held, at some
level, inside a <code class="literal">JWindow</code> or <code class="literal">JFrame</code>. Applets are a kind of <code class="literal">Container</code>. Even applets must be housed in a
frame or window, though normally you don’t see an applet’s parent frame
because it is part of (or simply is) the browser or <code class="literal">appletviewer</code> displaying the applet.</p><div class="figure"><a id="learnjava3-CHP-16-FIG-2"/><div class="figure-contents"><div class="mediaobject"><a id="I_16_tt981"/><img src="httpatomoreillycomsourceoreillyimages1707649.png.jpg" alt="A frame and a window"/></div></div><p class="title">Figure 16-2. A frame and a window</p></div><p><code class="literal">JFrames</code> and <code class="literal">JWindow</code>s are the only components that can be
displayed without being added or attached to another <code class="literal">Container</code>. After creating a <code class="literal">JFrame</code> or <code class="literal">JWindow</code>, you can call the <a id="I_indexterm16_id787716" class="indexterm"/><code class="literal">setVisible()</code> method to
display it. The following short application creates a <code class="literal">J