We used JScrollPane
earlier in this chapter without
explaining much about it. In this section we’ll remedy the
situation.
A JScrollPane
is a container that can hold one
component. Said another way, a JScrollPane
wraps another component. By default, if the
wrapped component is larger than the JScrollPane
itself, the JScrollPane
supplies scrollbars.
JScrollPane
handles the events from the scrollbars
and displays the appropriate portion of the contained component.
Technically, JScrollPane
is a
Container
, but it’s a funny one. It has its
own layout manager, which can’t be changed. It can accommodate
only one component at a time. This seems like a big limitation, but
it isn’t. If you want to put a lot of stuff in a
JScrollPane
, just put your components into a
JPanel
, with whatever layout manager you like, and
put that panel into the JScrollPane
.
When you create a JScrollPane
, you can
specify the conditions under which
its scrollbars will be displayed. This is called the
scrollbar display
policy
; a separate policy is used for the
horizontal and vertical scrollbars. The
following constants can be used to specify the policy for each of the
scrollbars:
HORIZONTAL_SCROLLBAR_AS_NEEDED
Displays a scrollbar only if the wrapped component doesn’t fit.
HORIZONTAL_SCROLLBAR_ALWAYS
Always shows a scrollbar, regardless of the contained component’s size.
HORIZONTAL_SCROLLBAR_NEVER
Never shows a scrollbar, even if the contained component won’t
fit. If you use this policy, you should provide some other way to
manipulate the JScrollPane
.
VERTICAL_SCROLLBAR_AS_NEEDED
Displays a scrollbar only if the wrapped component doesn’t fit.
VERTICAL_SCROLLBAR_ALWAYS
Always shows a scrollbar, regardless of the contained component’s size.
VERTICAL_SCROLLBAR_NEVER
Never shows a scrollbar, even if the contained component won’t
fit. If you use this policy, you should provide some other way to
manipulate the JScrollPane
.
By default, the policies are
HORIZONTAL_SCROLLBAR_AS_NEEDED
and
VERTICAL_SCROLLBAR_AS_NEEDED
.
Here’s an example that uses a
JScrollPane
to display a large image. The
application itself is very simple; all we do is place the image in an
ImageComponent
, wrap a JScrollPane
around it, and put the JScrollPane
in a
JFrame
’s content pane. Here’s the
code:
//file: ScrollPaneFrame.java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ScrollPaneFrame { public static void main(String[] args) { String filename = "Piazza di Spagna.jpg"; if (args.length > 0) filename = args[0]; JFrame f = new JFrame("ScrollPaneFrame v1.0"); f.setSize(300, 300); f.setLocation(200, 200); f.addWindowListener(new WindowAdapter( ) { public void windowClosing(WindowEvent e) { System.exit(0); } }); Image image = Toolkit.getDefaultToolkit( ).getImage(filename); f.getContentPane( ).add( new JScrollPane(new ImageComponent(image))); f.setVisible(true); } }
And here’s the ImageComponent
. It waits for
the image to load, using a
MediaTracker
, and sets its size to the size of the
image. It also provides a paint( )
method to draw the image. This takes a
single call to drawImage( )
. The first argument is the image
itself; the next two are the coordinates of the image relative to the
ImageComponent
; and the last is a reference to the
ImageComponent
itself (this
),
which serves
as an image observer. (We’ll
discuss image observers in Chapter 18; for the time
being, take this on faith.)
//file: ImageComponent.java import java.awt.*; import javax.swing.*; public class ImageComponent extends JComponent { Image image; Dimension size; public ImageComponent(Image image) { this.image = image; MediaTracker mt = new MediaTracker(this); mt.addImage(image, 0); try { mt.waitForAll( ); } catch (InterruptedException e) { // error ... }; size = new Dimension (image.getWidth(null), image.getHeight(null)); setSize(size); } public void paint(Graphics g) { g.drawImage(image, 0, 0, this); } public Dimension getPreferredSize( ) { return size; } }
Finally,
ImageComponent
provides a getPreferredSize( )
method, overriding
the method it inherits from Component
. This method
simply returns the image’s size, which is a
Dimension
object. When you’re using
JScrollPane
, it’s important for the object
you’re scrolling to provide a reliable indication of its size.
Figure 14.6 shows the
ScrollPaneFrame
with the
ImageComponent
.