Chapter 15 Scrolling Components
- In This Chapter
- The JViewport Class
- The JScrollPane Class
- JComponent Scrolling Support
We have seen the need for scrolling large components earlier in this book when dealing with the JList and JTable classes. Many applications contain data structures or pictures that cannot be displayed completely on the computers screen. Often this situation is handled by creating a large component displaying the data or picture and allowing the user to scroll the component to see the portion of the component that they want. When creating large lists and tables, we saw how easy it was to enable these components to be scrolled. At that time, however, the scrolling support contained in the JFC was not fully described. These capabilities are described in this chapter.
The JFC provides the JScrollPane class to allow any component to be easily scrolled. The JScrollPane class manages horizontal and vertical scrollbars, column and row header components, corner components, and a viewport. However, all components may not be visible in every scroll pane. The viewport in the scroll pane manages the actual component that is to be scrolled. The horizontal header scrolls right and left as the content scrolls, but not vertically. It is always on top of the data. The column header component behaves similarly, but for columns. It moves up and down with the content but does not move horizontally.
In this chapter, you will learn
- How the JViewport class works
- How the JScrollPane class works
- How to manage the scrollbar policy
- How to add headers to the scroll pane
The JViewport Class
The JViewport class is used by the JScrollPane class to manage the view of the underlying component being displayed in the scroll pane. The JViewport class extends the JComponent class. When a scrollbar contained in the scroll pane is scrolled, it is the viewport that moves. A viewport can be thought of as the viewer on a camcorder. As the camcorder is moved about, different portions of the scenery are visible in the viewer. As the camcorder moves right, additional scenery on the right is visible and scenery to the left is removed from the viewer. A viewport displaying a portion of a large component is shown in Figure 15.1.
Figure 15.1 JViewport instance displaying a portion of a large component.
The JViewport class contains a single default constructor. The constructor configures the viewport with its layout manager, a ViewportLayout instance by default. However, extensions of the JViewport can change the default layout manager by overriding the createLayoutManager method and returning a different layout manager. Typically, JViewport instances are not created by user code. Instead, the viewport created by the JScrollPane class is used. This is demonstrated later in this chapter.
A JViewport instance manages one child, a descendant of the AWT Component class. The child component can be a container itself and can contain many other components, but the viewport itself has only a single child. The child is set and queried with the setView and getView methods. When the component is set via the setView method, the viewport adds a component listener to the component. If the component is later resized, the viewport notifies listeners that have registered for changes by using the addChangeListener method. A listener is removed with the removeChangeListener method.
A viewport can be configured to create an offscreen image that buffers the visual representation of the visible portion of the child component. This allows the viewport to scroll faster. When the viewports paint method is called, if the viewport has not been scrolled, the component is drawn to the image that is then copied to the display. If the viewport has been scrolled, the image is moved the appropriate amount and then the exposed portion of the child component is drawn to the image. The complete image is then copied to the display. This allows scrolling to be performed faster by not having to repaint the entire component when a small scroll is performed. The offscreen image is known as a backing store. To enable the backing store, true is passed to the setBackingStoreEnabled method. The current state of this attribute can be queried via the isBackingStoreEnabled method.
Whether to use a backing store is a classic tradeoff between time and memory. Using the extra memory for the backing store allows the scrolling to be performed faster. Unfortunately, calling setBackingStoreEnabled with a parameter of false does not free the storage allocated for the backing store image. This means that once the backing store is enabled, the offscreen image will not be garbage collected until the entire viewport is eligible for garbage collection, even though it is no longer used.
When a component is first added to a viewport, its upper-left corner is aligned with the upper-left corner of the viewport. This will not be the case once the component is scrolled. If it is required to determine which portion of the view is visible, the JViewport class provides the getExtentSize and getViewPosition methods to query the size of the visible portion of the component and the position of the component in the upper-left corner of the viewport. The getViewRect method returns an AWT Rectangle instance that combines the information of the previous two calls. These locations as they relate to the underlying component are shown in Figure 15.2. The size of the underlying view can be queried with the getViewSize method. If the viewport does not contain a component, a size of (0,0) is returned. Otherwise the size of the component is returned. If the size has not been explicitly set, the preferred size of the component is returned.
Figure 15.2 JViewport class positioning of a large component.
|