Often you need to use a scrollbar to scroll the contents of an object that does not fit completely into the viewing area. JScrollBar and JSlider can be used for this purpose, but you have to manually write the code to implement scrolling with them. JScrollPane is a component that supports automatic scrolling without coding. It was used to scroll the text area in Listing 15.6, TextAreaDemo.java, and to scroll a list in Listing 15.8, ListDemo.java. In fact, it can be used to scroll any subclass of JComponent .
A JScrollPane can be viewed as a specialized container with a view port for displaying the contained component. In addition to horizontal and vertical scrollbars, a JScrollPane can have a column header, a row header, and corners, as shown in Figure 28.17.
The view port is an instance of JViewport through which a scrollable component is displayed. When you add a component to a scroll pane, you are actually placing it in the scroll pane's view port. Figure 28.18 shows the frequently used properties, constructors, and methods in JScrollPane .
The constructor always creates a view port regardless of whether the viewing component is specified. Normally, you have the component and you want to place it in a scroll pane. A convenient way to create a scroll pane for a component is to use the JScrollPane(component) constructor.
The vsbPolicy parameter can be one of the following three values:
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED JScrollPane.VERTICAL_SCROLLBAR_NEVER JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
The hsbPolicy parameter can be one of the following three values:
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED JScrollPane.HORIZONTAL_SCROLLBAR_NEVER JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
To set a corner component, you can use the setCorner(String key, Component corner) method. The legal values for the key are:
JScrollPane.LOWER_LEFT_CORNER JScrollPane.LOWER_RIGHT_CORNER JScrollPane.UPPER_LEFT_CORNER JScrollPane.UPPER_RIGHT_CORNER
Listing 28.9 shows an example that displays a map in a label and places the label in a scroll pane so that a large map can be scrolled. The program lets you choose a map from a combo box and display it in the scroll pane, as shown in Figure 28.19.
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 import javax.swing.border.*; 5 6 public class ScrollMap extends JApplet { 7 // Create images in labels 8 private JLabel lblIndianaMap = new JLabel( 9 new ImageIcon(getClass().getResource( "image/indianaMap.gif" ))); 10 private JLabel lblOhioMap = new JLabel( 11 new ImageIcon(getClass().getResource( "image/ohioMap.gif" ))); 12 13 // Create a scroll pane to scroll map in the labels 14 private JScrollPane jspMap = new JScrollPane(lblIndianaMap); 15 16 public ScrollMap() { 17 // Create a combo box for selecting maps 18 JComboBox jcboMap = new JComboBox( new String[]{ "Indiana" , 19 "Ohio" }); 20 21 // Panel p to hold combo box 22 JPanel p = new JPanel(); 23 p.setLayout( new BorderLayout()); 24 p.add(jcboMap); 25 p.setBorder( new TitledBorder( "Select a map to display" )); 26 27 // Set row header, column header and corner header 28 jspMap.setColumnHeaderView( new JLabel( new ImageIcon(getClass(). 29 getResource( "image/horizontalRuler.gif" )))); 30 jspMap.setRowHeaderView( new JLabel( new ImageIcon(getClass(). 31 getResource( "image/verticalRuler.gif" )))); 32 jspMap.setCorner(JScrollPane.UPPER_LEFT_CORNER, 33 new CornerPanel(JScrollPane.UPPER_LEFT_CORNER)); 34 jspMap.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, 35 new CornerPanel(JScrollPane.UPPER_RIGHT_CORNER)); 36 jspMap.setCorner(JScrollPane.LOWER_RIGHT_CORNER, 37 new CornerPanel(JScrollPane.LOWER_RIGHT_CORNER)); 38 jspMap.setCorner(JScrollPane.LOWER_LEFT_CORNER, 39 new CornerPanel(JScrollPane.LOWER_LEFT_CORNER)); 40 41 // Add the scroll pane and combo box panel to the frame 42 add(jspMap, BorderLayout.CENTER); 43 add(p, BorderLayout.NORTH); 44 45 // Register listener 46 jcboMap.addItemListener( new ItemListener() { 47 /** Show the selected map */ 48 public void itemStateChanged(ItemEvent e) { 49 String selectedItem = (String)e.getItem(); 50 if (selectedItem.equals( "Indiana" )) { 51 // Set a new view in the view port 52 jspMap.setViewportView(lblIndianaMap); 53 } 54 else if (selectedItem.equals( "Ohio" )) { 55 // Set a new view in the view port 56 jspMap.setViewportView(lblOhioMap); 57 } 58 59 // Revalidate the scroll pane 60 jspMap.revalidate(); 61 } 62 }); 63 } 64 } 65 66 // A panel displaying a line used for scroll pane corner 67 class CornerPanel extends JPanel { 68 // Line location 69 private String location; 70 71 public CornerPanel(String location) { 72 this .location = location; 73 } 74 75 /** Draw a line depending on the location */ 76 protected void paintComponent(Graphics g) { 77 super .paintComponents(g); 78 79 if (location == "UPPER_LEFT_CORNER" ) 80 g.drawLine( , getHeight(), getWidth(), ); 81 else if (location == "UPPER_RIGHT_CORNER" ) 82 g.drawLine( , , getWidth(), getHeight()); 83 else if (location == "LOWER_RIGHT_CORNER" ) 84 g.drawLine( , getHeight(), getWidth(), ); 85 else if (location == "LOWER_LEFT_CORNER" ) 86 g.drawLine( , , getWidth(), getHeight()); 87 } 88 } |
The program creates a scroll pane to view image maps. The images are created from image files and displayed in labels (lines 8 “11). To view an image, the label that contains the image is placed in the scroll pane's view port (line 14).
The scroll pane has a main view, a header view, a column view, and four corner views. Each view is a subclass of Component . Since ImageIcon is not a subclass of Component , it cannot be directly used as a view in the scroll pane. Instead the program places an ImageIcon to a label and uses the label as a view.
The CornerPanel (lines 67 “88) is a subclass of JPanel that is used to display a line. How the line is drawn depends on the location of the corner. The location is a string passed in as a parameter in the CornerPanel 's constructor.
Whenever a new map is selected, the label for displaying the map image is set to the scroll pane's view port. The revalidate() method (line 60) must be invoked to cause the new image to be displayed. The revalidate() method causes a container to lay out its subcomponents again after the components it contains have been added to or modified.