Using Components, the GUI Building Blocks |
Scrollbars have two uses:
- As shown above, a scrollbar can act as a slider that the user manipulates to set a value. An example of this is in the Converter program in The Anatomy of a a GUI-Based Program.
- As controls for scroll panes. The
ScrollPane
class, which was introduced in 1.1, lets you display part of a component that's too large for the available display area. Scrollbars in scroll panes let the user choose exactly which part of the region is visible. To customize scrolling behavior, you sometimes need to invoke methods on aScrollPane
's scrollbars.Here's a 1.0 applet that uses scrollbars to help control the display of a large image (it might take a minute for the image to load):
Note: The rest of this section discusses the 1.0 API for scrollbars. If you're writing a 1.1 program with a scrolling area, please skip the rest of this page and go to How to Use Scroll Panes.
To create a scrollbar, you need to create an instance of the
Scrollbar
class. You must also initialize the following values, either by specifying them to a Scrollbar constructor or by calling thesetValues()
method before the scrollbar is visible.Here's a figure that illustrates the meaning of the above values:
int orientation
- Indicates whether the scrollbar should be horizontal or vertical. Specified with either
Scrollbar.HORIZONTAL
orScrollbar.VERTICAL
.int value
- The initial value of the scrollbar. For scrollbars that control a scrollable area, this usually means the x value (for horizontal scrollbars) or y value (for vertical scrollbars) of the part of the area that's visible when the user first sees the scrollable area. For example, when the applet above starts up, both the horizontal and vertical scrollbars' values are 0, and the image portion that's displayed starts at (0,0).
int visible
- The size in pixels of the visible portion of the scrollable area. This value, if set before the scrollbar is visible, determines how many pixels a click in the scrollbar (but not on the knob) causes the display area to shift. Setting this value after the scrollbar is visible has no effect. After the scrollbar is visible, you should use the
setPageIncrement()
method to get the same effect.int minimum
- The minimum value the scrollbar can have. For scrollbars controlling scrollable areas, this value is usually 0 (the left/upper part of the area).
int maximum
- The maximum value the scrollbar can have. For scrollbars controlling scrollable areas, this value is usually: (total width/height, in pixels, of the component that's being partially displayed) - (currently visible width/height of the scrollable area).
Here's the code for the above applet. The code defines two classes. The first is a simple Canvas subclass (ScrollableCanvas) that draws an image. The second is a Panel subclass (ImageScroller, which actually extends Applet) that creates and contains a ScrollableCanvas and two Scrollbars. This program illustrates a few important details of managing a scrollable area:
- Event handling for a scrollbar is pretty straightforward. The program must merely respond to scrolling events by saving the scrollbar's new value in a place accessible to the Component that displays itself within the scrollable area, and then invoke
repaint()
on the Component.public boolean handleEvent(Event evt) { switch (evt.id) { case Event.SCROLL_LINE_UP: case Event.SCROLL_LINE_DOWN: case Event.SCROLL_PAGE_UP: case Event.SCROLL_PAGE_DOWN: case Event.SCROLL_ABSOLUTE: if (evt.target == vert) { canvas.ty = ((Integer)evt.arg).intValue(); canvas.repaint(); } if (evt.target == horz) { canvas.tx = ((Integer)evt.arg).intValue(); canvas.repaint(); } } return super.handleEvent(evt); }- The Component that displays itself within the scrollable area can be very simple. All it needs to do is draw itself at the origin specified by the values from its controlling scrollbars. A Component can change its origin (and thus not have to change its normal drawing code) by putting code such as the following at the beginning of its
paint()
orupdate()
method:g.translate(-tx, -ty);- While scrolling occurs, you'll probably notice flashing, or flickering, in the display area. If you don't want this to occur, you'll need to implement the
update()
method in the displayed Component, and possibly double buffering as well. How to do this is discussed in Eliminating Flashing.
- If your scrolling area is resizable, beware of a common scrolling problem. It occurs when the user scrolls to the right/bottom of the area and then enlarges the area. If you aren't careful, the scrolling area will display a blank space at its right/bottom. After the user scrolls and then returns to the right/bottom, the blank space will no longer be there. To avoid displaying a blank space unnecessarily, when the scrollable area's size becomes larger you should shift the Component's origin so that it takes advantage of the available new space. Here's an example:
int canvasWidth = canvas.size().width; //Shift everything to the right if we're displaying empty space //on the right side. if ((canvas.tx + canvasWidth) > imageSize.width) { int newtx = imageSize.width - canvasWidth; if (newtx < 0) { newtx = 0; } canvas.tx = newtx; }Here's a figure that illustrates the scrolling problem and its fix:
Using Components, the GUI Building Blocks |