ScrollPane
A ScrollPane
is a Container
with built-in scrollbars that can be used to scroll its contents. In the current implementation, a ScrollPane
can hold only one Component
and has no layout manager. The component within a ScrollPane
is always given its preferred size. While the scrollpane's inability to hold multiple components sounds like a deficiency, it isn't; there's no reason you can't put a Panel
inside a ScrollPane
, put as many components as you like inside the Panel
, and give the Panel
any layout manager you wish.
Scrolling is handled by the ScrollPane
peer, so processing is extremely fast. In Example 11.1, the user moves a Scrollbar
to trigger a scrolling event, and the peer sends the event to the Java program to find someone to deal with it. Once it identifies the target, it posts the event, then tries to find a handler. Eventually, the applet's handleEvent()
method is called to reposition the ImageCanvas
. The new position is then given to the peer, which finally redisplays the Canvas
. Although most of the real work is behind the scenes, it is still happening. With ScrollPane
, the peer generates and handles the event itself, which is much more efficient.
ScrollPane Methods
ConstantsThe ScrollPane
class contains three constants that can be used to control its scrollbar display policy. The constants are fairly self-explanatory. The constants are used in the constructor for a ScrollPane
instance.
- public static final int SCROLLBARS_AS_NEEDED
SCROLLBARS_AS_NEEDED
is the default scrollbar display policy. With this policy, theScrollPane
displays each scrollbar only if theComponent
is too large in the scrollbar's direction.- public static final int SCROLLBARS_ ALWAYS
- With the
SCROLLBARS_ALWAYS
display policy, theScrollPane
should always display both scrollbars, whether or not they are needed. - public static final int SCROLLBARS_ NEVER
- With the
SCROLLBARS_NEVER
display policy, theScrollPane
should never display scrollbars, even when the object is bigger than theScrollPane
's area. When using this mode, you should provide some means for the user to scroll, either through a button outside the container or by listening for events happening within the container.
- public ScrollPane ()
- The first constructor creates an instance of
ScrollPane
with the default scrollbar display policy setting,SCROLLBARS_AS_NEEDED
. - public ScrollPane (int scrollbarDisplayPolicy)
- The other constructor creates an instance of
ScrollPane
with a scrollbar setting ofscrollbarDisplayPolicy
. IfscrollbarDisplayPolicy
is not one of the class constants, this constructor throws theIllegalArgumentException
run-time exception.
- public final void setLayout(LayoutManager mgr)
- The
setLayout()
method ofScrollPane
throws anAWTError
. It overrides thesetLayout()
method ofContainer
to prevent you from changing aScrollPane
's layout manager. - public void doLayout ()
public void layout () - The
doLayout()
method ofScrollPane
shapes the contained object to its preferred size.layout()
is another name for this method. - public final void addImpl(Component comp, Object constraints, int index)
- The
addImpl()
method ofScrollPane
permits only one object to be added to theScrollPane
. It overides theaddImpl()
method ofContainer
to enforce theScrollPane
's limitations on adding components. Ifindex > 0
,addImpl()
throws the run-time exceptionIllegalArgumentException
. If a component is already within theScrollPane
, it is removed beforecomp
is added. Theconstraints
parameter is ignored.
- public int getScrollbarDisplayPolicy()
- The
getScrollbarDisplayPolicy()
method retrieves the current display policy, as set by the constructor. You cannot change the policy once it has been set. The return value is one of the class constants:SCROLLBARS_AS_NEEDED
,SCROLLBARS_ALWAYS
, orSCROLLBARS_NEVER
. - public Dimension getViewportSize()
- The
getViewportSize()
method returns the current size of theScrollPane
, less anyInsets
, as aDimension
object. The size is given in pixels and has an initial value of 100 x 100. - public int getHScrollbarHeight()
- The
getHScrollbarHeight()
method retrieves the height in pixels of a horizontal scrollbar. The value returned is without regard to the display policy; that is, you may be given a height even if the scrollbar is not displayed. This method may return 0 if the scrollbar's height cannot be calculated at this time (no peer) or if you are using theSCROLLBARS_NEVER
display policy.The width of a horizontal scrollbar is just
getViewportSize().width
. - public int getVScrollbarWidth()
- The
getVScrollbarWidth()
method retrieves the width in pixels of a vertical scrollbar. The value returned is without regard to the display policy; that is, you may be given a width even if the scrollbar is not displayed. This method may return 0 if the scrollbar's width cannot be calculated at this time (no peer) or if you are using theSCROLLBARS_NEVER
display policy.The height of a vertical scrollbar is just
getViewportSize().height
. - public Adjustable getHAdjustable()
- The
getHAdjustable()
method returns the adjustable object representing the horizontal scrollbar (ornull
if it is not present). Through the methods ofAdjustable
, you can get the different settings of the scrollbar.The object that this method returns is an instance of the package private class
ScrollPaneAdjustable
, which implements theAdjustable
interface. this class allows you to register listeners for the scrollpane's events and inquire about various properties of the pane's scrollbars. It does not let you set some scrollbar properties; thesetMinimum()
,setMaximum()
, andsetVisibleAmount()
methods throw anAWTError
when called. - public Adjustable getVAdjustable()
- The
getVAdjustable()
method returns the adjustable object representing the vertical scrollbar (ornull
if it is not present). Through the methods ofAdjustable
, you can get the different settings of the scrollbar.The object that this method returns is an instance of the package private class
ScrollPaneAdjustable
, which implements theAdjustable
interface. this class allows you to register listeners for the scrollpane's events and inquire about various properties of the pane's scrollbars. It does not let you set some scrollbar properties; thesetMinimum()
,setMaximum()
, andsetVisibleAmount()
methods throw anAWTError
when called. - public void setScrollPosition(int x, int y)
- This
setScrollPosition()
method moves theScrollPane
to the designated location if possible. Thex
andy
arguments are scrollbar settings, which should be interpreted in terms of the minimum and maximum values given to you by the horizontal and verticalAdjustable
objects (returned by the previous two methods). If theScrollPane
does not have a child component, this method throws the run-time exceptionNullPointerException
. You can also move theScrollPane
by calling theAdjustable.setValue()
method of one of the scrollpane'sAdjustable
objects. - public void setScrollPosition(Point p)
- This
setScrollPosition()
method calls the previous with parameters ofp.x
, andp.y
. - public Point getScrollPosition()
- The
getScrollPosition()
method returns the current position of both the scrollpane'sAdjustable
objects as aPoint
. If there is no component within theScrollPane
,getScrollPosition()
throws theNullPointerException
run-time exception. Another way to get this information is by calling theAdjustable.getValue()
method of eachAdjustable
object.
- public void printComponents (Graphics g)
- The
printComponents()
method ofScrollPane
prints the single component it contains. This is done by clipping the contextg
to the size of the display area and calling the contained component'sprintAll()
method. - public synchronized void addNotify ()
- The
addNotify()
method creates theScrollPane
peer. If you override this method, callsuper.addNotify()
first, then add your customizations for the new class. You will then be able to do everything you need with the information about the newly created peer. - protected String paramString ()
ScrollPane
doesn't have its owntoString()
method; so when you call thetoString()
method of aScrollPane
, you are actually calling theComponent.toString()
method. This in turn callsparamString()
, which builds the string to display. For aScrollPane
,paramString()
adds the current scroll position, insets, and scrollbar display policy. For example:
java.awt.ScrollPane[scrollpane0,0,0,0x0,invalid,ScrollPosition=(0,0), Insets=(0,0,0,0),ScrollbarDisplayPolicy=always]
ScrollPane Events
The ScrollPane
peer deals with the scrolling events for you. It is not necessary to catch or listen for these events. As with any other Container
, you can handle the 1.0 events of the object you contain or listen for 1.1 events that happen within you.
Using a ScrollPane
The following applet demonstrates one way to use a ScrollPane
. Basically, you place the object you want to scroll in the ScrollPane
by calling the add()
method. This can be a Panel
with many objects on it or a Canvas
with an image drawn on it. You then add as many objects as you want to the Panel
or scribble on the Canvas
to your heart's delight. No scrolling event handling is necessary. That is all there is to it. To make this example a little more interesting, whenever you select a button, the ScrollPane
scrolls to a randomly selected position. Figure 11.4 displays the screen.
Figure 11.4: A ScrollPane containing many buttons
Here's the code:
// Java 1.1 only import java.awt.*; import java.awt.event.*; import java.applet.*; public class scroll extends Applet implements ActionListener, ContainerListener { ScrollPane sp = new ScrollPane (ScrollPane.SCROLLBARS_ALWAYS); public void init () { setLayout (new BorderLayout ()); Panel p = new Panel(new GridLayout (7, 8)); p.addContainerListener (this); for (int j=0;j<50;j++) p.add (new Button ("Button-" + j)); sp.add (p); add (sp, "Center"); } public void componentAdded(ContainerEvent e) { if (e.getID() == ContainerEvent.COMPONENT_ADDED) { if (e.getChild() instanceof Button) { Button b = (Button)e.getChild(); b.addActionListener(this); } } } public void componentRemoved(ContainerEvent e) { } public void actionPerformed (ActionEvent e) { Component c = sp.getComponent(); Dimension d = c.getSize(); sp.setScrollPosition ((int)(Math.random()*d.width), (int)(Math.random()*d.height)); } }
Working with the ScrollPane
itself is easy; we just create one, add a Panel
to it, set the Panel
's layout manager to GridLayout
, and add a lot of buttons to the Panel
. The applet itself is the action listener for all the buttons; when anybody clicks a button, actionPerformed()
is called, which generates a new random position based on the viewport size and sets the new scrolling position accordingly by calling setScrollPosition()
.
The more interesting part of this applet is the way it works with buttons. Instead of directly adding a listener for each button, we add a ContainerListener
to the containing panel and let it add listeners. Although this may seem like extra work here, it demonstrates how you can use container events to take actions whenever someone adds or removes a component. At first glance, you might ask why I didn't just call enableEvents(AWTEvent.CONTAINER_EVENT_MASK)
and override the applet's processContainerEvent()
to attach the listeners. If we were only adding our components to the applet, that would work great. Unfortunately, the applet is not notified when buttons are added to an unrelated panel. It would be notified only when the panel was added to the applet.