31.6. Custom Table Renderers and Editors

 
[Page 920 ( continued )]

28.3. Layout Managers

Every container has a layout manager that is responsible for arranging its components . The container's setLayout method can be used to set a layout manager. Certain types of containers have default layout managers. For instance, the content pane of JFrame or JApplet uses BorderLayout , and JPanel uses FlowLayout .

The layout manager places the components in accordance with its own rules and property settings, and with the constraints associated with each component. Every layout manager has its own specific set of rules. For example, the FlowLayout manager places components in rows from left to right and starts a new row when the previous row is filled. The BorderLayout manager places components in the north, south, east, west, or center of the container. The GridLayout manager places components in a grid of cells in rows and columns from left to right in order.

Some layout managers have properties that can affect the sizing and location of the components in the container. For example, BorderLayout has properties called hgap (horizontal gap) and vgap (vertical gap) that determine the distance between components horizontally and vertically. FlowLayout has properties that can be used to specify the alignment (left, center, right) of the components and properties for specifying the horizontal or vertical gap between the components. GridLayout has properties that can be used to specify the horizontal or vertical gap between columns and rows and properties for specifying the number of rows and columns. These properties can be retrieved and set using their accessor and mutator methods .

The size of a component in a container is determined by many factors, such as:

  • The type of layout manager used by the container.

  • The layout constraints associated with each component.

  • The size of the container.

  • Certain properties common to all components (such as preferredSize , minimumSize , maximumSize , alignmentX , and alignmentY ).

The preferredSize property indicates the ideal size at which the component looks best. Depending on the rules of the particular layout manager, this property may or may not be considered . For example, the preferred size of a component is used in a container with a FlowLayout manager, but ignored if it is placed in a container with a GridLayout manager.


[Page 921]

The minimumSize property specifies the minimum size at which the component is useful. For most GUI components, minimumSize is the same as preferredSize . Layout managers generally respect minimumSize more than preferredSize .

The maximumSize property specifies the maximum size needed by a component, so that the layout manager won't wastefully give space to a component that does not need it. For instance, BorderLayout limits the center component's size to its maximum size, and gives the space to edge components.

The alignmentX ( alignmentY ) property specifies how the component would like to be aligned relative to other components along the x -axis ( y -axis). This value should be a number between and 1 , where represents alignment along the origin, 1 is aligned the farthest away from the origin, 0.5 is centered, and so on. These two properties are used in the BoxLayout and OverlayLayout .

Java provides a variety of layout managers. You have learned how to use BorderLayout , FlowLayout , and GridLayout . The following sections introduce CardLayout , GridBagLayout , Null layout, BoxLayout , OverlayLayout , and SpringLayout .

Tip

If you set a new layout manager in a container, invoke the container's validate() method to force the container to again lay out the components. If you change the properties of a layout manager in a JFrame or JApplet , invoke the doLayout() method to force the container to again layout the components using the new layout properties. If you change the properties of a layout manager in a JPanel , invoke either doLayout() or revalidate() method to force it to again layout the components using the new layout properties, but it is better to use revalidate() . Note that validate() is a public method defined in java.awt.Container , revalidate() is a public method defined in javax.swing.JComponent , and doLayout() is a public method defined in java.awt.Container .


28.3.1. CardLayout

CardLayout places components in the container as cards. Only one card is visible at a time, and the container acts as a stack of cards. The ordering of cards is determined by the container's own internal ordering of its component objects. You can specify the size of the horizontal and vertical gaps surrounding a stack of components in a CardLayout manager, as shown in Figure 28.2.

Figure 28.2. The CardLayout places components in the container as a stack of cards.

CardLayout defines a set of methods that allow an application to flip through the cards sequentially or to show a specified card directly, as shown in Figure 28.3.


[Page 922]
Figure 28.3. CardLayout contains the methods to flip the card.

To add a component into a container, use the add(Component c, String name ) method defined in the Container class interface. The String parameter, name , gives an explicit identity to the component in the container.

Listing 28.1 gives a program that creates two panels in a frame. The first panel uses CardLayout to hold six labels for displaying images. The second panel uses FlowLayout to group four buttons named First, Next , Previous, and Last, and a combo box labeled Image , as shown in Figure 28.4.

Figure 28.4. The program shows images in a panel of CardLayout .


These buttons control which image will be shown in the CardLayout panel. When the user clicks the button named First, for example, the first image in the CardLayout panel appears. The combo box enables the user to directly select an image.

Listing 28.1. ShowCardLayout.java
(This item is displayed on pages 922 - 924 in the print version)
 1   import   java.awt.*; 2   import   java.awt.event.*; 3   import   javax.swing.*; 4 

[Page 923]
 5   public class   ShowCardLayout   extends   JApplet { 6    private   CardLayout cardLayout =   new   CardLayout(   20   ,   10   );  7   private   JPanel cardPanel =    new   JPanel(cardLayout)  ; 8   private   JButton jbtFirst, jbtNext, jbtPrevious, jbtLast; 9   private   JComboBox jcboImage; 10   private final int   NUM_OF_FLAGS =   6   ; 11 12   public   ShowCardLayout() { 13 cardPanel.setBorder( 14   new   javax.swing.border.LineBorder( Color .red)); 15 16  // Add 9 labels for displaying images into cardPanel  17   for   (   int   i =   1   ; i <= NUM_OF_FLAGS; i++) { 18 JLabel label = 19   new   JLabel(   new   ImageIcon(   "image/flag"   + i +   ".gif"   )); 20 cardPanel.add(label, String.valueOf(i)); 21 } 22 23  // Panel p to hold buttons and a combo box  24 JPanel p =   new   JPanel(); 25 p.add(jbtFirst =   new   JButton(   "First"   )); 26 p.add(jbtNext =   new   JButton(   "Next"   )); 27 p.add(jbtPrevious=   new   JButton(   "Previous"   )); 28 p.add(jbtLast =   new   JButton(   "Last"   )); 29 p.add(   new   JLabel(   "Image"   )); 30 p.add(jcboImage =   new   JComboBox()); 31 32  // Initialize combo box items  33   for   (   int   i =   1   ; i <= NUM_OF_FLAGS; i++) 34 jcboImage.addItem(String.valueOf(i)); 35 36  // Place panels in the frame  37 add(cardPanel, BorderLayout.CENTER); 38 add(p, BorderLayout.SOUTH); 39 40  // Register listeners with the source objects  41  jbtFirst.addActionListener(   new   ActionListener() {  42   public void   actionPerformed(ActionEvent e) { 43  // Show the first component in cardPanel  44  cardLayout.first(cardPanel);  45 } 46 }); 47  jbtNext.addActionListener(   new   ActionListener() {  48   public void   actionPerformed(ActionEvent e) { 49  // Show the first component in cardPanel  50  cardLayout.next(cardPanel);  51 } 52 }); 53  jbtPrevious.addActionListener(   new   ActionListener() {  54   public void   actionPerformed(ActionEvent e) { 55  // Show the first component in cardPanel  56  cardLayout.previous(cardPanel);  57 } 58 }); 59  jbtLast.addActionListener(   new   ActionListener() {  60   public void   actionPerformed(ActionEvent e) { 61  // Show the first component in cardPanel  62  cardLayout.last(cardPanel);  63 } 64 }); 

[Page 924]
 65  jcboImage.addItemListener(   new   ItemListener() {  66   public void   itemStateChanged(ItemEvent e) { 67  // Show the component at specified index  68  cardLayout.show(cardPanel, (String)e.getItem());  69 } 70 }); 71 } 72 } 

An instance of CardLayout is created in line 6, and a panel of CardLayout is created in line 7. You have already used such statements as setLayout(new FlowLayout()) to create an anonymous layout object and set the layout for a container, instead of declaring and creating a separate instance of the layout manager, as in this program. The cardLayout object, however, is useful later in the program to show components in cardPanel . You have to use cardLayout.first(cardPanel) (line 44), for example, to view the first component in cardPanel .

The statement in lines 17 “21 adds the image label with the identity String.valueOf(i) . Later, when the user selects an image with number i , the identity String.valueOf(i) is used in the show method (line 68) to view the image with the specified identity.

28.3.2. (Optional) The GridBagLayout Manager

The GridBagLayout manager is the most flexible and the most complex. It is similar to the GridLayout manager in the sense that both layout managers arrange components in a grid. The components of GridBagLayout can vary in size, however, and can be added in any order. For example, with GridBagLayout you can create the layout shown in Figure 28.5.

Figure 28.5. A GridBagLayout manager divides the container into cells. A component can occupy several cells.


The constructor GridBagLayout() is used to create a new GridBagLayout . In GridLayout , the grid size (the number of rows and columns) may be specified in the constructor. It is not specified in GridBagLayout . The actual size is dynamically determined by the constraints associated with the components added to the container of GridBagLayout .

Each GridBagLayout uses a dynamic rectangular grid of cells, with each component occupying one or more cells called its display area . Each component managed by a GridBagLayout is associated with a GridBagConstraints instance that specifies how the component is laid out within its display area. How a GridBagLayout places a set of components depends on the GridBagConstraints and minimum size of each component, as well as the preferred size of the component's container.

To use GridBagLayout effectively, you must customize the GridBagConstraints of one or more of its components. You customize a GridBagConstraints object by setting one or more of its public instance variables. These variables specify the component's location, size, growth factor, anchor, inset, filling, and padding.


[Page 925]
Location

The variables gridx and gridy specify the cell at the upper left of the component's display area, where the upper-leftmost cell has the address gridx=0 , gridy=0 . Note that gridx specifies the column in which the component will be placed, and gridy specifies the row in which it will be placed. In Figure 28.5, Button 1 has a gridx value of 1 and a gridy value of 3 , and Label has a gridx value of 0 and a gridy value of 0.

You can assign GridBagConstraints.RELATIVE to gridx to specify that the component be placed immediately after the component that was just added to the container. You can assign GridBagConstraints.RELATIVE to gridy to specify that the component be placed immediately below the component that was just added to the container.

Size

The variables gridwidth and gridheight specify the number of cells in a row (for gridheight ) or column (for gridwidth ) in the component's display area. The default value is 1 . In Figure 28.5, the JPanel in the center occupies two columns and two rows, so its gridwidth is 2 , and its gridheight is 2 . Text Area 2 occupies one row and one column; therefore its gridwidth is 1 , and its gridheight is 1 .

You can assign GridBagConstraints.RELATIVE.REMAINDER to gridwidth ( gridheight ) to specify that the component is to be the last one in its row (column).

Growth Weight

The variables weightx and weighty specify the extra horizontal and vertical space to allocate for the component when the resulting layout is smaller horizontally than the area it needs to fill.

The GridBagLayout manager calculates the weight of a column to be the maximum weightx ( weighty ) of all the components in a column (row). The extra space is distributed to each column (row) in proportion to its weight.

Unless you specify a weight for at least one component in a row ( weightx ) and a column ( weighty ), all the components clump together in the center of their container. This is because, when the weight is zero (the default), the GridBagLayout puts any extra space between its grid of cells and the edges of the container. You will see the effect of these parameters in Listing 28.2.

Anchor

The variable anchor specifies where in the area the component is placed when it does not fill the entire area. Valid values are:

 GridBagConstraints.CENTER (the default) GridBagConstraints.NORTH GridBagConstraints.NORTHEAST GridBagConstraints.EAST GridBagConstraints.SOUTHEAST GridBagConstraints.SOUTH GridBagConstraints.SOUTHWEST GridBagConstraints.WEST GridBagConstraints.NORTHWEST 

Filling

The variable fill specifies how the component should be resized if its viewing area is larger than its current size. Valid values are GridBagConstraints.NONE (the default), GridBagConstraints.HORIZONTAL (makes the component wide enough to fill its display area horizontally, but doesn't change its height), GridBagConstraints.VERTICAL (makes the component tall enough to fill its display area vertically, but doesn't change its width), and GridBagConstraints.BOTH (makes the component totally fill its display area).


[Page 926]
Insets

The variable insets specifies the external padding of the component, the minimum amount of space between the component and the edges of its display area. The default value is new Insets(0, 0, 0, 0) .

Padding

The variables ipadx and ipady specify the internal padding of the component: how much space to add to its minimum width and height. The width of the component is at least its minimum width plus ( ipadx * 2) pixels, and the height of the component is at least its minimum height plus ( ipady * 2) pixels. The default value of these variables is . The insets variable specifies the external padding, while the ipadx and ipady variables specify the internal padding, as shown in Figure 28.6.

Figure 28.6. You can specify the external insets and internal padding for a component in the container of the GridBagLayout manager.


Constructing a GridBagConstraints Object

There are two constructors for creating a GridBagConstraints object:

  • public GridBagConstraints()

    Constructs a GridBagConstraints object with all of its fields set to their default values.

  • public GridBagConstraints( int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty, int anchor, int fill, Insets insets, int ipadx, int ipady)

    Constructs a GridBagConstraints object with the specified field values.

Adding a Component to the Container of GridBagLayout

To add a component to the container of GridBagLayout , use the following method in the container:

   public void   add(Component comp, Object gbConstraints) 

Adds a component to the container with the specified GridBagConstraints .

Example: Using GridBagLayout

Listing 28.2 gives a program that uses the GridBagLayout manager to create a layout for Figure 28.5. The output of the program is shown in Figure 28.7.


[Page 927]
Figure 28.7. The components are placed in the frame of GridBagLayout .


Listing 28.2. ShowGridBagLayout.java
(This item is displayed on pages 927 - 928 in the print version)
 1   import   java.awt.*; 2   import   javax.swing.*; 3 4   public class   ShowGridBagLayout   extends   JApplet { 5   private   JLabel jlbl =   new   JLabel( 6   "Resize the Window and Study GridBagLayout"   , JLabel.CENTER); 7   private   JTextArea jta1 =   new   JTextArea(   "Text Area 1"   ,   5   ,   15   ); 8   private   JTextArea jta2 =   new   JTextArea(   "Text Area 2"   ,   5   ,   15   ); 9   private   JTextField jtf =   new   JTextField(   "JTextField"   ); 10   private   JPanel jp =   new   JPanel(); 11   private   JButton jbt1 =   new   JButton(   "Button 1"   ); 12   private   JButton jbt2 =   new   JButton(   "Button 2"   ); 13 14   public   ShowGridBagLayout() { 15  // Set GridBagLayout in the container  16 setLayout(    new   GridBagLayout()  ); 17 18  // Create an GridBagConstraints object  19  GridBagConstraints gbConstraints =   new   GridBagConstraints();  20 21  gbConstraints.fill  = GridBagConstraints.BOTH; 22  gbConstraints.anchor  = GridBagConstraints.CENTER; 23 24 Container container = getContentPane(); 25 26  // Place JLabel to occupy row 0 (the first row)  27  addComp(jlbl, container, gbConstraints,     ,     ,   1   ,   4   ,     ,     );  28 29  // Place text area 1 in row 1 and 2, and column 0  30 addComp(jta1, container, gbConstraints,   1   ,     ,   2   ,   1   ,   5   ,   1   ); 31 32  // Place text area 2 in row 1 and column 3  33 addComp(jta2, container, gbConstraints,   1   ,   3   ,   1   ,   1   ,   5   ,   1   ); 34 35  // Place text field in row 2 and column 3  36 addComp(jtf, container, gbConstraints,   2   ,   3   ,   1   ,   1   ,   5   ,     ); 37 38  // Place JButton 1 in row 3 and column 1  39 addComp(jbt1, container, gbConstraints,   3   ,   1   ,   1   ,   1   ,   5   ,     ); 40 41  // Place JButton 2 in row 3 and column 2  42 addComp(jbt2, container, gbConstraints,   3   ,   2   ,   1   ,   1   ,   5   ,     ); 43 44  // Place Panel in row 1 and 2, and column 1 and 2  45 jp.setBackground(Color.red); 46 jp.setBorder(   new   javax.swing.border.LineBorder(Color.black)); 

[Page 928]
 47 gbConstraints.insets =   new   Insets(   10   ,   10   ,   10   ,   10   ); 48 addComp(jp, container, gbConstraints,   1   ,   1   ,   2   ,   2   ,   10   ,   1   ); 49 } 50 51  /** Add a component to the container of GridBagLayout */  52   private void    addComp(Component c, Container container,  53  GridBagConstraints gbConstraints,  54    int   row,   int   column,  55    int   numberOfRows,   int   numberOfColumns,  56    double   weightx,   double   weighty)  { 57  // Set parameters  58  gbConstraints.gridx  = column; 59  gbConstraints.gridy  = row; 60  gbConstraints.gridwidth  = numberOfColumns; 61  gbConstraints.gridheight  = numberOfRows; 62  gbConstraints.weightx  = weightx; 63  gbConstraints.weighty  = weighty; 64 65  // Add component to the container with the specified layout  66  container.add(c, gbConstraints);  67 } 68 } 

The program defines the addComp method (lines 52 “67) to add a component to the container of GridBagLayout with the specified constraints. The GridBagConstraints object gbConstraints created in line 19 is used to specify the layout constraints for each component. Before adding a component to the container, set the constraints in gbConstraints and then use container.add(c, gbConstraints) (line 66) to add the component to the container.

What would happen if you change the weightx parameter for jbt2 to 10 in line 41? Now jbt2 's weightx is larger than jbt1 's. When you enlarge the window, jbt2 will get larger horizontally than jbt1 .

The weightx and weighty for all the other components are . Whether the size of these components grows or shrinks depends on the fill parameter. The program defines fill = BOTH for all the components added to the container (line 27).

Consider this scenario: Suppose that you enlarge the window. The display area for text area jta1 will increase. Because fill is BOTH for jta1 , jta1 fills in its new display area. If you set fill to NONE for jta1 , jta1 will not expand or shrink when you resize the window.

The insets parameter is ( , , , ) by default. For the panel jp , insets is set to ( 10 , 10 , 10 , 10 ) (line 47).

28.3.3. Using No Layout Manager

If you have used a Windows-based RAD tool like Visual Basic, you know that it is easier to create user interfaces with Visual Basic than with Java. This is mainly because the components are placed in absolute positions and sizes in Visual Basic, whereas they are placed in containers using a variety of layout managers in Java. Absolute positions and sizes are fine if the application is developed and deployed on the same platform, but what looks fine on a development system may not look right on a deployment system. To solve this problem, Java provides a set of layout managers that place components in containers in a way that is independent of fonts, screen resolutions , and platform differences.

For convenience, Java also supports an absolute layout that enables you to place components at fixed locations. In this case, the component must be placed using the component's instance method setBounds() (defined in java.awt.Component ), as follows :

   public void   setBounds(   int   x,   int   y,   int   width,   int   height); 


[Page 929]

This sets the location and size for the component, as in the next example:

 JButton jbt =   new   JButton(   "Help"   ); jbt.setBounds(   10   ,   10   ,   40   ,   20   ); 

The upper-left corner of the Help button is placed at (10, 10); the button width is 40, and the height is 20.

You perform the following steps in order not to use a layout manager:

1.
Use this statement to specify no layout manager:

 setLayout(    null    ); 

2.
Add the component to the container:

 add(jbt); 

3.
Specify the location where the component is to be placed, using the setBounds method:

 JButton jbt =  new  JButton(   "Help"   ); jbt.setBounds(   10   ,   10   ,   40   ,   20   ); 

Listing 28.3 gives a program that places the same components in the same layout as in the preceding example but without using a layout manager. Figure 28.8 contains the sample output.

Figure 28.8. The components are placed in the frame without using a layout manager.


Listing 28.3. ShowNoLayout.java
(This item is displayed on pages 929 - 930 in the print version)
 1   import   java.awt.*; 2   import   javax.swing.*; 3 4   public class   ShowNoLayout   extends   JApplet { 5   private   JLabel jlbl = 6   new   JLabel(   "Resize the Window and Study No Layout"   , 7 JLabel.CENTER); 8   private   JTextArea jta1 =   new   JTextArea(   "Text Area 1"   ,   5   ,   10   ); 9   private   JTextArea jta2 =   new   JTextArea(   "Text Area 2"   ,   5   ,   10   ); 10   private   JTextField jtf =   new   JTextField(   "TextField"   ); 11   private   JPanel jp =   new   JPanel(); 12   private   JButton jbt1 =   new   JButton(   "Cancel"   ); 13   private   JButton jbt2 =   new   JButton(   "Ok"   ); 14   private   GridBagLayout gbLayout; 15   private   GridBagConstraints gbConstraints; 16 17   public   ShowNoLayout() { 18  // Set background color for the panel  19 jp.setBackground(Color.red); 

[Page 930]
 20 21  // Specify no layout manager  22 setLayout(   null   ); 23 24   // Add components to frame   25 add(jlbl); 26 add(jp); 27 add(jta1); 28 add(jta2); 29 add(jtf); 30 add(jbt1); 31 add(jbt2); 32 33  // Put components in the right place  34  jlbl.setBounds(     ,   10   ,   400   ,   40   );  35  jta1.setBounds(     ,   50   ,   100   ,   100   );  36  jp.setBounds(   100   ,   50   ,   200   ,   100   );  37  jta2.setBounds(   300   ,   50   ,   100   ,   50   );  38  jtf.setBounds(   300   ,   100   ,   100   ,   50   );  39  jbt1.setBounds(   100   ,   150   ,   100   ,   50   );  40  jbt2.setBounds(   200   ,   150   ,   100   ,   50   );  41 } 42 } 

If you run this program on Windows with 640 x 480 resolution, the layout size is just right. When the program is run on Windows with a higher resolution, the components appear very small and clump together. When it is run on Windows with a lower resolution, they cannot be shown in their entirety.

If you resize the window, you will see that the location and size of the components are not changed, as shown in Figure 28.9.

Figure 28.9. With no layout manager, the size and positions of the components are fixed.


Tip

Do not use the no-layout-manager option to develop platform-independent applications.


28.3.4. BoxLayout

javax.swing.BoxLayout is a Swing layout manager that arranges components in a row or a column. To create a BoxLayout , use the following constructor:

   public   BoxlayLayout(Container target,   int   axis) 


[Page 931]

This constructor is different from other layout constructors. It creates a layout manager that is dedicated to the given target container. The axis parameter is BoxLayout.X_AXIS or BoxLayout.Y_AXIS , which specifies whether the components are laid out horizontally or vertically. For example, the following code creates a horizontal BoxLayout for panel p1 :

 JPanel p1 =   new   JPanel(); BoxLayout boxLayout =   new   BoxLayout(p1, BoxLayout.X_AXIS); p1.setLayout(boxLayout); 

You still need to invoke the setLayout method on p1 to set the layout manager.

You can use BoxLayout in any container, but it is simpler to use the Box class, which is a container of BoxLayout . To create a Box container, use one of the following two static methods:

 Box box1 = Box.createHorizontalBox(); Box box2 = Box.createVerticalBox(); 

The former creates a box that contains components horizontally, and the latter creates a box that contains components vertically.

You can add components to a box in the same way that you add them to the containers of FlowLayout or GridLayout using the add method, as follows:

 box1.add(new JButton(   "A Button"   )); 

You can remove components from a box in the same way that you drop components to a container. The components are laid left to right in a horizontal box, and top to bottom in a vertical box.

BoxLayout is similar to GridLayout but has many unique features.

First, BoxLayout respects a component's preferred size, maximum size, and minimum size. If the total preferred size of all the components in the box is less than the box size, then the components are expanded up to their maximum size. If the total preferred size of all the components in the box is greater than the box size, then the components are shrunk down to their minimum size. If the components do not fit at their minimum width, some of them will not be shown. In the GridLayout , the container is divided into cells of equal size, and the components are fit in regardless of their preferred maximum or minimum size.

Second, unlike other layout managers, BoxLayout considers the component's alignmentX or alignmentY property. The alignmentX property is used to place the component in a vertical box layout, and the alignmentY property is used to place it in a horizontal box layout.

Third, BoxLayout does not have gaps between the components, but you can use fillers to separate components. A filler is an invisible component. There are three kinds of fillers: struts, rigid areas, and glues.

A strut simply adds some space between components. The static method createHorizontalStrut(int) in the Box class is used to create a horizontal strut, and the static method createVerticalStrut(int) to create a vertical strut. For example, the code shown below adds a vertical strut of 8 pixels between two buttons in a vertical box:

 box2.add(   new   JButton(   "Button 1"   )); box2.add(Box.createVerticalStrut(   8   )); box2.add(   new   JButton(   "Button 2"   )); 

A rigid area is a two-dimensional space that can be created using the static method createRigidArea(dimension) in the Box class. For example, the next code adds a rigid area 10 pixels wide and 20 pixels high into a box.

 box2.add(Box.createRigidArea(   new   Dimension(   10   ,   20   )); 


[Page 932]

A glue separates components as much as possible. For example, by adding a glue between two components in a horizontal box, you place one component at the left end and the other at the right end. A glue can be created using the Box.createGlue() method.

Listing 28.4 shows an example that creates a horizontal box and a vertical box. The horizontal box holds two buttons with print and save icons. The vertical box holds four buttons for selecting flags. When a button in the vertical box is clicked, a corresponding flag icon is displayed in the label centered in the applet, as shown in Figure 28.10.

Figure 28.10. The components are placed in the containers of BoxLayout .


Listing 28.4. ShowBoxLayout.java
(This item is displayed on pages 932 - 933 in the print version)
 1   import   java.awt.*; 2   import   java.awt.event.*; 3   import   javax.swing.*; 4 5   public class   ShowBoxLayout   extends   JApplet { 6  // Create two box containers  7    private   Box box1 = Box.createHorizontalBox();  8    private   Box box2 = Box.createVerticalBox();  9 10  // Create a label to display flags  11   private   JLabel jlblFlag =   new   JLabel(); 12 13  // Create image icons for flags  14   private   ImageIcon imageIconUS = 15   new   ImageIcon(getClass().getResource(   "/image/us.gif"   )); 16   private   ImageIcon imageIconCanada = 17   new   ImageIcon(getClass().getResource(   "/image/ca.gif"   )); 18   private   ImageIcon imageIconNorway = 19   new   ImageIcon(getClass().getResource(   "/image/norway.gif"   )); 20   private   ImageIcon imageIconGermany = 21   new   ImageIcon(getClass().getResource(   "/image/ germany .gif"   )); 22   private   ImageIcon imageIconPrint = 23   new   ImageIcon(getClass().getResource(   "/image/print.gif"   )); 24   private   ImageIcon imageIconSave = 25   new   ImageIcon(getClass().getResource(   "/image/save.gif"   )); 26 27  // Create buttons to select images  28   private   JButton jbtUS =   new   JButton(   "US"   ); 29   private   JButton jbtCanada =   new   JButton(   "Canada"   ); 30   private   JButton jbtNorway =   new   JButton(   "Norway"   ); 31   private   JButton jbtGermany =   new   JButton(   "Germany"   ); 32 33   public   ShowBoxLayout() { 34  box1.add(   new   JButton(imageIconPrint));  35 box1.add(Box.createHorizontalStrut(   20   )); 36 box1.add(   new   JButton(imageIconSave)); 

[Page 933]
 37 38  box2.add(jbtUS);  39 box2.add(Box.createVerticalStrut(   8   )); 40 box2.add(jbtCanada); 41 box2.add(Box.createGlue()); 42 box2.add(jbtNorway); 43 box2.add(Box.createRigidArea(   new   Dimension(   10   ,   8   ))); 44 box2.add(jbtGermany); 45 46  box1.setBorder(   new   javax.swing.border.LineBorder(Color.red));  47  box2.setBorder(   new   javax.swing.border.LineBorder(Color.black));  48 49 add(box1, BorderLayout.NORTH); 50 add(box2, BorderLayout.EAST); 51 add(jlblFlag, BorderLayout.CENTER); 52 53  // Register listeners  54 jbtUS.addActionListener(   new   ActionListener() { 55   public void   actionPerformed(ActionEvent e) { 56 jlblFlag.setIcon(imageIconUS); 57 } 58 }); 59 jbtCanada.addActionListener(   new   ActionListener() { 60   public void   actionPerformed(ActionEvent e) { 61 jlblFlag.setIcon(imageIconCanada); 62 } 63 }); 64 jbtNorway.addActionListener(   new   ActionListener() { 65   public void   actionPerformed(ActionEvent e) { 66 jlblFlag.setIcon(imageIconNorway); 67 } 68 }); 69 jbtGermany.addActionListener(   new   ActionListener() { 70   public void   actionPerformed(ActionEvent e) { 71 jlblFlag.setIcon(imageIconGermany); 72 } 73 }); 74 } 75 } 

Two containers of the Box class are created in lines 7 “8 using the convenient static methods createHorizontalBox() and createVerticalBox() . You could also create it using the constructor Box(int axis) . The box containers always use the BoxLayout manager. You cannot reset the layout manager for the box containers.

The image icons are created from image files (lines 14 “25) through resource bundles, which was introduced in §16.9, "Locating Resource Using the URL Class."

Two buttons with print and save icons are added into the horizontal box (lines 34 “36). A horizontal strut with size 20 is added between these two buttons (line 35).

Four buttons with texts US, Canada, Norway, and Germany are added into the vertical box (lines 38 “44). A horizontal strut with size 8 is added to separate the US button and the Canada button (line 39). A rigid area is inserted between the Norway button and the Germany button (line 43). A glue is inserted to separate the Canada button and the Norway button as far as possible in the vertical box (line 41).

The strut, rigid area, and glue are instances of Component , so they can be added to the box container. In theory, you can add them to a container other than the box container. But they may be ignored and have no effect in other containers.


[Page 934]

28.3.5. (Optional) OverlayLayout

OverlayLayout is a Swing layout manager that arranges components on top of each other. To create an OverlayLayout , use the following constructor:

   public   OverlayLayout(Container target) 

The constructor creates a layout manager that is dedicated to the given target container. For example, the following code creates an OverlayLayout for panel p1 :

 JPanel p1 =   new   JPanel(); OverlayLayout overlayLayout =   new   OverlayLayout(p1); p1.setLayout(overlayLayout); 

You still need to invoke the setLayout method on p1 to set the layout manager.

A component is on top of another component if it is added to the container before the other one. Suppose components p1 , p2 , and p3 are added to a container of the OverlayLayout in this order, then p1 is on top of p2 , and p2 is on top of p3 .

Listing 28.5 gives an example that overlays two buttons in a panel of OverlayLayout , as shown in Figure 28.11. The first button is on top of the second button. The program enables the user to set the alignmentX and alignmentY properties of the two buttons dynamically. You can also set the opaque (blocked) property of the first button. When the opaque property is set to true , the first button blocks the scene of the second button, as shown in Figure 28.11(a). When the opaque property is set to false , the first button becomes transparent to allow the second button to be seen through the first button, as shown in Figure 28.11(b).

Figure 28.11. The components are overlaid in the container of OverlayLayout .

Listing 28.5. ShowOverLayLayout.java
(This item is displayed on pages 934 - 936 in the print version)
 1   import   java.awt.*; 2   import   java.awt.event.*; 3   import   javax.swing.*; 4 5   public class   ShowOverlayLayout   extends   JApplet { 6   private   JButton jbt1 =   new   JButton(   "Button 1"   ); 7   private   JButton jbt2 =   new   JButton(   "Button 2"   ); 8 9   private   JTextField jtfButton1AlignmentX =   new   JTextField(   4   ); 10   private   JTextField jtfButton1AlignmentY =   new   JTextField(   4   ); 11   private   JTextField jtfButton2AlignmentX =   new   JTextField(   4   ); 12   private   JTextField jtfButton2AlignmentY =   new   JTextField(   4   ); 13   private   JComboBox jcboButton1Opaque =   new   JComboBox( 14   new   Object[]{   new   Boolean(   true   ),   new   Boolean(   false   )}); 

[Page 935]
 15 16  // Panel p1 to hold two buttons  17   private   JPanel p1 =   new   JPanel(); 18 19   public   ShowOverlayLayout() { 20  // Add two buttons to p1 of OverlayLayout  21  p1.setLayout(   new   OverlayLayout(p1));  22  p1.add(jbt1);  23  p1.add(jbt2);  24 25 JPanel p2 =   new   JPanel(); 26 p2.setLayout(   new   GridLayout(   5   ,   1   )); 27 p2.add(   new   JLabel(   "Button 1's alignmentX"   )); 28 p2.add(   new   JLabel(   "Button 1's alignmentY"   )); 29 p2.add(   new   JLabel(   "Button 2's alignmentX"   )); 30 p2.add(   new   JLabel(   "Button 2's alignmentY"   )); 31 p2.add(   new   JLabel(   "Button 1's opaque"   )); 32 33 JPanel p3 =   new   JPanel(); 34 p3.setLayout(   new   GridLayout(   5   ,   1   )); 35 p3.add(jtfButton1AlignmentX); 36 p3.add(jtfButton1AlignmentY); 37 p3.add(jtfButton2AlignmentX); 38 p3.add(jtfButton2AlignmentY); 39 p3.add(jcboButton1Opaque); 40 41 JPanel p4 =   new   JPanel(); 42 p4.setLayout(   new   BorderLayout(   4   ,   4   )); 43 p4.add(p2, BorderLayout.WEST); 44 p4.add(p3, BorderLayout.CENTER); 45 46 add(p1, BorderLayout.CENTER); 47 add(p4, BorderLayout.WEST); 48 49  jtfButton1AlignmentX.addActionListener(   new   ActionListener() {  50   public void   actionPerformed(ActionEvent e) { 51 jbt1.setAlignmentX( 52 Float.parseFloat(jtfButton1AlignmentX.getText())); 53 p1.revalidate();  // Cause the components to be rearranged  54 p1.repaint();  // Cause the viewing area to be repainted  55 } 56 }); 57  jtfButton1AlignmentY.addActionListener(   new   ActionListener() {  58   public void   actionPerformed(ActionEvent e) { 59 jbt1.setAlignmentY( 60 Float.parseFloat(jtfButton1AlignmentY.getText())); 61 p1.revalidate();  // Cause the components to be rearranged  62 p1.repaint();  // Cause the viewing area to be repainted  63 } 64 }); 65  jtfButton2AlignmentX.addActionListener(   new   ActionListener() {  66   public void   actionPerformed(ActionEvent e) { 67 jbt2.setAlignmentX( 68 Float.parseFloat(jtfButton2AlignmentX.getText())); 69 p1.revalidate();  // Cause the components to be rearranged  70 p1.repaint();  // Cause the viewing area to be repainted  71 } 72 }); 73  jtfButton2AlignmentY.addActionListener(   new   ActionListener() {  74   public void   actionPerformed(ActionEvent e) { 

[Page 936]
 75 jbt2.setAlignmentY( 76 Float.parseFloat(jtfButton2AlignmentY.getText())); 77 p1.revalidate();  // Cause the components to be rearranged  78 p1.repaint();  // Cause the viewing area to be repainted  79 } 80 }); 81  jcboButton1Opaque.addActionListener(   new   ActionListener() {  82   public void   actionPerformed(ActionEvent e) { 83 jbt1.setOpaque(((Boolean)(jcboButton1Opaque. 84 getSelectedItem())).booleanValue()); 85 p1.revalidate();  // Cause the components to be rearranged  86 p1.repaint();  // Cause the viewing area to be repainted  87 } 88 }); 89 } 90 } 

A panel p1 of OverlayLayout is created (line 21) to hold two buttons (lines 22 “23). Since Button 1 is added before Button 2, Button 1 is on top of Button 2.

The alignmentX and alignmentY properties specify how the two buttons are aligned relative to each other along the x -axis and y -axis (lines 51, 59). These two properties are used in BoxLayout and OverlayLayout , but are ignored by other layout managers. Note that the alignment is a float type number between and 1 .

The opaque property is defined in JComponent for all Swing lightweight components. By default, it is true for JButton , which means that the button is nontransparent. So if Button 1's opaque is true , you cannot see any other components behind JButton 1. To enable the components behind Button 1 to be seen, set Button 1's opaque property to false (lines 83 “86).

28.3.6. (Optional) SpringLayout

SpringLayout is a new Swing layout manager introduced in JDK 1.4. The idea of SpringLayout is to put a flexible spring around a component. The spring may compress or expand to place the components in desired locations.

To create a SpringLayout , use its no-arg constructor:

   public   SpringLayout() 

A spring is an instance of the Spring class that can be created using one of the following two static methods:

  • public static Spring constant( int pref)

    Returns a spring whose minimum, preferred, and maximum values each have the value pref .

  • public static Spring constant( int min, int pref, int max)

    Returns a spring with the specified minimum, preferred, and maximum values.

Each spring has a preferred value, minimum value, maximum value, and actual value. The getPreferredValue() , getMinimumValue() , getMaximumValue() , and getValue() methods retrieve these values. The setValue(int value) method can be used to set an actual value.

The Spring class defines the static sum(Spring s1, Spring s2) to produce a combined new spring, the static minus(Spring s) to produce a new spring running in the opposite direction, and the static max(Spring s1, Spring s2) to produce a new spring with larger values from s1 and s2 .


[Page 937]

To add a spring or a fixed space to separate components in the container, use one of the following two methods in the SpringLayout class:

  • public void putConstraint(String e1, Component c1, Spring s, String e2, Component c2)

    Places a spring between edge e1 of component c1 and edge e2 of component c2 , anchored on c2 . Each edge must have one of the following values: SpringLayout.NORTH , SpringLayout.SOUTH , SpringLayout.EAST , SpringLayout.WEST .

  • public void putConstraint(String e1, Component c1, int pad, String e2, Component c2)

    Places a fixed pad between edge e1 of component c1 and edge e2 of component c2 , anchored on c2 .

In the preceding methods, e2 and c2 are referred to as the anchor edge and anchor component , and e1 and c1 as the dependent edge and dependent component .

Listing 28.6 gives an example that places a button in the center of the container, as shown in Figure 28.12.

Figure 28.12. The button is centered in the container of SpringLayout .


Listing 28.6. ShowSpringLayout.java
 1   import   java.awt.*; 2   import   javax.swing.*; 3 4   public class   ShowSpringLayout   extends   JApplet { 5   public   ShowSpringLayout() { 6  SpringLayout springLayout =   new   SpringLayout();  7  JPanel p1 =   new   JPanel(springLayout);  8 JButton jbt1 =   new   JButton(   "Button 1"   ); 9 p1.add(jbt1); 10 11 Spring spring = Spring.constant(     ,   1000   ,   2000   ); 12  springLayout.putConstraint(SpringLayout.WEST, jbt1, spring,  13  SpringLayout.WEST, p1);  14 springLayout.putConstraint(SpringLayout.EAST, p1, spring, 15 SpringLayout.EAST, jbt1); 16 springLayout.putConstraint(SpringLayout.NORTH, jbt1, spring, 17 SpringLayout.NORTH, p1); 18 springLayout.putConstraint(SpringLayout.SOUTH, p1, spring, 19 SpringLayout.SOUTH, jbt1); 20 21 add(p1, BorderLayout.CENTER); 22 } 23 } 

A SpringLayout named springLayout is created in line 6 and is set in JPanel p1 (line 7). An instance of Spring is created using the static constant method with minimum value , preferred value 1000 , and maximum value 2000 (line 11).


[Page 938]

Like icons and borders, an instance of Spring can be shared. The putConstraint method in SpringLayout puts a spring between two components. In lines 12 “13, the spring is padded between the west of the button and the west of the panel p1 , anchored at p1 . In lines 14 “15, the same spring is padded between the east of the panel and the east of the button, anchored at the button. The selection of the anchor components is important. For example, if lines 12 “13 were replaced by the following code,

 springLayout.putConstraint(SpringLayout.WEST, p1, spring, SpringLayout.WEST, jbt1); 

the button would be pushed all the way to the east, as shown in Figure 28.13(a). If lines 12 “13 were replaced by the following code,

 springLayout.putConstraint(SpringLayout.NORTH, p1, spring, SpringLayout.NORTH, jbt1); 

Figure 28.13. The selection of the anchor component can affect the layout.

the button would be pushed all the way to the top, as shown in Figure 28.13(b).

If lines 14 “15 were replaced by the following code,

 springLayout.putConstraint(SpringLayout.EAST, p1,  Spring.sum(spring, spring)  , SpringLayout.EAST, jbt1); 

the spring on the right of the button is twice strong as the left spring of the button, as shown in Figure 28.13(c).

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net