Layout manager in Java

how many layout managers in java and layout manager in java examples programs and explain layout manager in java
JohenCorner Profile Pic
JohenCorner,France,Professional
Published Date:02-08-2017
Your Website URL(Optional)
Comment
Layout Managers A layout manager arranges the child components of a container, as shown in Figure 19-1. It positions and sets the size of components within the container’s display area according to a particular layout scheme. The layout manager’s job is to fit the components into the available area while maintaining some spatial relationships among them. AWT and Swing come with several standard layout managers that will collectively handle most situations; you can also make your own layout managers if you have special requirements. Figure 19-1. A layout manager at work Every container has a default layout manager. When you make a new container, it comes with aLayoutManager object of the appropriate type. You can install a new layout man‐ ager at any time by using thesetLayout() method. For example, we can set the layout manager of a Swing container to a type calledBorderLayout like so: myContainer.setLayout( new BorderLayout() ); 709 a Notice that although we have created a BorderLayout, we haven’t bothered to save a reference to it. This is typical; after installing a layout manager, it usually does its work behind the scenes by interacting with the container. You rarely call the layout manager’s methods directly, so you don’t usually need a reference (a notable exception isCardLay out). However, you do need to know what the layout manager is going to do with your components as you work with them. The LayoutManager is consulted whenever a container’s doLayout() method is called to reorganize the contents. It does its job by calling the setLocation() or set Bounds() methods of the individual child components to arrange them in the container’s display area. A container is laid out the first time it is displayed and thereafter whenever the container’s revalidate() method is called. Containers that are a subclass of the Window class (Frame, JFrame, and JWindow) are automatically validated whenever they are packed or resized. Calling pack() sets the window’s size as small as possible while granting all its components their preferred sizes. Every component provides three important pieces of information used by the layout manager in placing and sizing it: a minimum size, a maximum size, and a preferred size. These sizes are reported by the getMinimumSize(), getMaximumSize(), and getPre ferredSize() methods ofComponent, respectively. For example, a plainJButton object can normally be changed to any size. However, the button’s designer can provide a preferred size for a good-looking button. The layout manager might use this size when there are no other constraints, or it might ignore it, depending on its scheme. If we give the button a label, the button may need a new minimum size to display itself properly. The layout manager should generally respect the button’s minimum size and guarantee that it has at least that much space. Similarly, a particular component might not be able to display itself properly if it is too large (perhaps it has to scale up an image); it can use getMaximumSize() to report the largest size it considers acceptable. The preferred size of aContainer object has the same meaning as for any other type of component. However, because aContainer may hold its own components and want to arrange them in its own layout, its preferred size is a function of its layout manager. The layout manager is, therefore, involved in both sides of the issue. It asks the components in its container for their preferred (or minimum) sizes in order to arrange them. Based on those values, it calculates the preferred size for its own container (which can then be communicated to the container’s parent and so on). When a layout manager is called to arrange its components, it is working within a fixed area. It usually begins by looking at its container’s dimensions and the preferred or minimum sizes of the child components. It then doles out screen area and sets the sizes of components according to its scheme and specific constraints. You can set the minimum, preferred, and maximum sizes for a component with the setMinimumSize(),setMaximumSize(), andsetPreferredSize() methods. Take care when setting these properties because generally those values should be calculated based 710 Chapter 19: Layout Managers a on the real conditions of the component, not just fixed at a static value that looks good in one particular case. You can override the getMinimumSize(), getMaximumSize(), andgetPreferredSize() methods of your own components to allow them to calculate those values, but you should do this only if you are specializing the component and it has new needs. In general, if you find yourself fighting with a layout manager because it’s changing the size of one of your components, you are probably using the wrong kind of layout manager or not composing your user interface properly. Often it’s easier to use a number of JPanel objects in a given display, each one with its ownLayoutManag er. Try breaking down the problem: place related components in their ownJPanel and then arrange the panels in the container. When that becomes unwieldy, use a constraint- based layout manager such as GridBagLayout or SpringLayout, which we’ll discuss later in this chapter. FlowLayout FlowLayout is a simple layout manager that tries to arrange components at their pre‐ ferred sizes, from left to right and top to bottom in the container. A FlowLayout can have a specified row justification ofLEFT,CENTER, or RIGHT and a fixed horizontal and vertical padding. By default, a flow layout uses CENTER justification, meaning that all components are centered within the area allotted to them.FlowLayout is the default for JPanels. The following example adds five buttons to the content pane of a JFrame using the defaultFlowLayout: //file: Flow.java import java.awt.; import java.awt.event.; import javax.swing.; public class Flow extends JPanel public Flow() // FlowLayout is default layout manager for a JPanel add(new JButton("One")); add(new JButton("Two")); add(new JButton("Three")); add(new JButton("Four")); add(new JButton("Five")); public static void main(String args) JFrame frame = new JFrame("Flow"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(400, 75); frame.setLocation(200, 200); Flow flow = new Flow(); FlowLayout 711 a frame.setContentPane(flow); frame.setVisible(true); The result is shown in Figure 19-2. Figure 19-2. A flow layout Try resizing the window. If it is made narrow enough, some of the buttons will spill over to a second or third row. GridLayout GridLayout arranges components into regularly spaced rows and columns. The com‐ ponents are arbitrarily resized to fit the grid; their minimum and preferred sizes are consequently ignored. GridLayout is most useful for arranging identically sized objects—perhaps a set ofJPanels, each using a different layout manager. GridLayout takes the number of rows and columns in its constructor. If you subse‐ quently give it too many objects to manage, it adds extra columns to make the objects fit. You can also set the number of rows or columns to 0, which means that you don’t care how many elements the layout manager packs in that dimension. For example, GridLayout(2,0) requests a layout with two rows and an unlimited number of columns; 1 if you put 10 components into this layout, you’ll get 2 rows of 5 columns each. The following example sets aGridLayout with three rows and two columns as its layout manager: //file: Grid.java import java.awt.; import java.awt.event.; import javax.swing.; public class Grid extends JPanel public Grid() setLayout(new GridLayout(3, 2)); 1. Callingnew GridLayout(0, 0) causes a runtime exception; either the rows or columns parameter must be greater than zero. 712 Chapter 19: Layout Managers a add(new JButton("One")); add(new JButton("Two")); add(new JButton("Three")); add(new JButton("Four")); add(new JButton("Five")); public static void main(String args) JFrame frame = new JFrame("Grid"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(200, 200); frame.setLocation(200, 200); frame.setContentPane(new Grid()); frame.setVisible(true); The results are shown in Figure 19-3. Figure 19-3. A grid layout The five buttons are laid out in order from left to right, top to bottom, with one empty spot. BorderLayout BorderLayout is a little more interesting. It tries to arrange objects in one of five geo‐ graphical locations, represented by constants in theBorderLayout class:NORTH,SOUTH, EAST, WEST, and CENTER, optionally with some padding between. BorderLayout is the default layout for the content panes ofJWindow andJFrame objects. Because each com‐ ponent is associated with a direction, BorderLayout can manage at most five compo‐ nents; it squashes or stretches those components to fit its constraints. As we’ll see in the second example, this means that you often want to have BorderLayout manage sets of components in their own panels. When we add a component to a container with a border layout, we need to specify both the component and the position at which to add it. To do so, we use an overloaded BorderLayout 713 a version of the container’s add() method that takes an additional argument as a con‐ straint. The constraint specifies the name of a position within theBorderLayout. The following application sets aBorderLayout and adds our five buttons again, named for their locations: //file: Border1.java import java.awt.; import java.awt.event.; import javax.swing.; public class Border1 extends JPanel public Border1() setLayout(new BorderLayout()); add(new JButton("North"), BorderLayout.NORTH ); add(new JButton("South"), BorderLayout.SOUTH ); add(new JButton("East"), BorderLayout.EAST ); add(new JButton("West"), BorderLayout.WEST ); add(new JButton("Center"), BorderLayout.CENTER ); public static void main(String args) JFrame frame = new JFrame("Border1"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(300, 300); frame.setLocation(200, 200); frame.setContentPane(new Border1()); frame.setVisible(true); The result is shown in Figure 19-4. Figure 19-4. A border layout So, how exactly is the area divided up? Well, the objects at NORTH and SOUTH get their preferred height and fill the display area horizontally. EAST and WEST components, on the other hand, get their preferred width and fill the remaining area betweenNORTH and 714 Chapter 19: Layout Managers a SOUTH vertically. Finally, theCENTER object takes all the rest of the space. As you can see in Figure 19-4, our buttons get distorted into interesting shapes. What if we don’t want BorderLayout messing with the sizes of our components? One option would be to put each button in its own JPanel. The default layout for a JPa nel isFlowLayout, which respects the preferred size of components. The preferred sizes of the panels are effectively the preferred sizes of the buttons, but if the panels are stretched, they won’t pull their buttons with them. The following application illustrates this approach: //file: Border2.java import java.awt.; import java.awt.event.; import javax.swing.; public class Border2 extends JPanel public Border2() setLayout(new BorderLayout()); JPanel p = new JPanel(); p.add(new JButton("North")); add(p, BorderLayout.NORTH); p = new JPanel(); p.add(new JButton("South")); add(p, BorderLayout.SOUTH); p = new JPanel(); p.add(new JButton("East")); add(p, BorderLayout.EAST); p = new JPanel(); p.add(new JButton("West")); add(p, BorderLayout.WEST); p = new JPanel(); p.add(new JButton("Center")); add(p, BorderLayout.CENTER); public static void main(String args) JFrame frame = new JFrame("Border2"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(225, 150); frame.setLocation(200, 200); frame.setContentPane(new Border2()); frame.setVisible(true); The result is shown in Figure 19-5. In the example, we create a number of panels, put our buttons inside the panels, and put the panels into the frame window, which has the BorderLayout manager. Now, the JPanel for the CENTER button soaks up the extra space that comes from the BorderLayout 715 a BorderLayout. EachJPanel’sFlowLayout centers the button in the panel and uses the button’s preferred size. In this case, it’s all a bit awkward. We’ll see how we could ac‐ complish this more directly usingGridBagLayout shortly. Figure 19-5. Another border layout BoxLayout Most layout managers are part of the java.awt package and were defined back when Java was first released. Swing adds a couple of new general-purpose layout managers in thejavax.swing package; one isBoxLayout. This layout manager is useful for creating simple toolbars or vertical button bars. It lays out components in a single row or column. It is similar toFlowLayout except that it does not wrap components into new rows. Although you can useBoxLayout directly, Swing includes a handy container calledBox that takes care of the details for you. EveryBox usesBoxLayout, but you don’t really have to worry about it; the Box class includes some very useful methods for laying out components. You can create a horizontal or vertical box usingBox’s static methods. Container horizontalBox = Box.createHorizontalBox(); Container verticalBox = Box.createVerticalBox(); Once theBox is created, you canadd() components as usual: Container box = Box.createHorizontalBox(); box.add(new JButton("In the")); Box includes several other static methods that create special invisible components that can be used to guide theBoxLayout. The first of these is glue; glue is really space between components in theBox. When theBox is resized, glue expands or contracts as more or less space is available. The other special invisible component type is a strut. Like glue, a strut represents space between components, but it doesn’t resize. The following example creates a horizontal Box (shown in Figure 19-6) that includes both glue and struts. Play around by resizing the window to see the effect of the glue and the struts. //file: Boxer.java import java.awt.; 716 Chapter 19: Layout Managers a import java.awt.event.; import javax.swing.; public class Boxer extends JPanel public static void main(String args) JFrame frame = new JFrame("Boxer"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(250, 250); frame.setLocation(200, 200); Container box = Box.createHorizontalBox(); box.add(Box.createHorizontalGlue()); box.add(new JButton("In the")); box.add(Box.createHorizontalGlue()); box.add(new JButton("clearing")); box.add(Box.createHorizontalStrut(10)); box.add(new JButton("stands")); box.add(Box.createHorizontalStrut(10)); box.add(new JButton("a")); box.add(Box.createHorizontalGlue()); box.add(new JButton("boxer")); box.add(Box.createHorizontalGlue()); frame.getContentPane().add(box, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); Figure 19-6. Using the Box class Components are added sequentially for display from left to right or top to bottom with optional glue or strut constraints placed between them. By default, components simply line up one after another with no space between them. Glue acts like a spring, allowing its adjacent components to move to occupy the space evenly. A strut imposes a fixed space between adjacent components. CardLayout CardLayout is a special layout manager for creating the effect of a “stack” of components. Instead of arranging all of the container’s components, it displays only one at a time. You might use this kind of layout to implement a custom-tabbed panel of some kind. In fact, there’s probably little reason to use this layout given the Swing JTabbedPane component described in Chapter 17. We include it here mainly for completeness. CardLayout 717 a To add a component to a CardLayout, use a two-argument version of the container’s add() method; the extra argument is an arbitrary string that serves as the card’s name: add("netconfigscreen", myComponent); To bring a particular card to the top of the stack, call theCardLayout’sshow() method with two arguments: the parentContainer and the name of the card you want to show. There are also methods—first(),last(),next(), andprevious()—for working with the stack of cards. These are all CardLayout instance methods. To invoke them, you need a reference to theCardLayout object itself, not to the container it manages. Each method takes a single argument: the parentContainer. Here’s an example: //file: Card.java import java.awt.; import java.awt.event.; import javax.swing.; public class Card extends JPanel CardLayout cards = new CardLayout(); public Card() setLayout(cards); ActionListener listener = new ActionListener() public void actionPerformed(ActionEvent e) cards.next(Card.this); ; JButton button; button = new JButton("one"); button.addActionListener(listener); add(button, "one"); button = new JButton("two"); button.addActionListener(listener); add(button, "two"); button = new JButton("three"); button.addActionListener(listener); add(button, "three"); public static void main(String args) JFrame frame = new JFrame("Card"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(200, 200); frame.setLocation(200, 200); frame.setContentPane(new Card()); frame.setVisible(true); We add three buttons to the layout and cycle through them as they are pressed. An anonymous inner class serves as an action listener for each button; it simply calls 718 Chapter 19: Layout Managers a CardLayout’s next() method whenever a button is pressed. Card.this refers to the Card object, which is the container in this case. In a more realistic example, we would build a group of panels, each of which might implement some part of a complex user interface and add those panels to the layout. Each panel would have its own layout manager. The panels would be resized to fill the entire area available (i.e., the area of the Container they are in), and their individual layout managers would arrange their in‐ ternal components. GridBagLayout GridBagLayout is a very flexible layout manager that allows you to position components relative to one another using constraints. With GridBagLayout (and a fair amount of effort), you can create almost any imaginable layout. Components are arranged at logical coordinates on an abstract grid. We call them “logical” coordinates because they des‐ ignate positions in the space of rows and columns formed by the set of components. Rows and columns of the grid stretch to different sizes, based on the sizes and constraints of the components they hold. A row or column in a GridBagLayout expands to accommodate the dimensions and constraints of the largest component it contains. Individual components may also be told to span more than one row or column. Components that aren’t as large as their grid cell can be anchored (positioned to one side) within their cell. They can also be set to fill or expand their size in either dimension. Extra area in the grid rows and columns can be parceled out according to the weight constraints of the components. In this way, you can control how various components will grow and stretch when a window is resized. GridBagLayout is much easier to use in a graphical WYSIWYG GUI builder environ‐ ment. That’s because working withGridBag is kind of like messing with the old rabbit- ears antennae on your television. It’s not particularly difficult to get the results that you want through trial and error, but writing out hard and fast rules for how to go about it is difficult. In short,GridBagLayout is complex and has some quirks. It is also simply a bit ugly both in model and implementation. Remember that you can do a lot with nested panels and by composing simpler layout managers within one another. If you look back through this chapter, you’ll see some examples of composite layouts; it’s up to you to determine how far you should go before making the break from simpler layout managers to a more complex all-in-one layout manager likeGridBagLayout. The GridBagConstraints Class Having stated that GridBagLayout is complex and a bit ugly, we’re going to contradict ourselves a little and say that its API is surprisingly simple. There is only one constructor with no arguments—GridBagLayout()—and there aren’t a lot of fancy methods to control how the display works. GridBagLayout 719 a The appearance of a grid bag layout is controlled by sets of GridBagConstraints, and that’s where things get hairy. Each component that is managed by a GridBagLayout is associated with a GridBagConstraints object.GridBagConstraints holds the follow‐ ing variables, which we’ll describe in detail shortly: int gridx int gridy Controls the position of the component on the layout’s grid int weightx int weighty Controls how additional space in the row or column is allotted to the component int fill Controls whether the component expands to fill the allotted space int gridheight int gridwidth Controls the number of rows or columns the component spans int anchor Controls the position of the component if there is extra room within the allotted space int ipadx int ipady Controls padding between the component and the borders of its area Insets insets Controls padding between the component and neighboring components To make a set of constraints for a component or components, create a new instance of GridBagConstraints and set these public variables to the appropriate values. (There is also a large constructor that takes all 11 arguments.) The easiest way to associate a set of constraints with a component is to use the version ofadd() that takes both a component object and a layout object as arguments. This puts the component in the container and associates theGridBagConstraints object with it: Container content = getContentPane(); JComponent component = new JLabel("constrain me, please..."); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = x; constraints.gridy = y; ... content.add(component, constraints); 720 Chapter 19: Layout Managers a You can also add a component to a GridBagLayout using the single argument add() method and then calling the layout’s setConstraints() method directly to pass it the GridBagConstraints object for that component: add(component); ... myGridBagLayout.setConstraints(component, constraints); In either case, the set of constraints is copied when it is applied to the component. It’s the individual constraints that apply to the component, not the GridBagConstraints object. Therefore, you’re free to create a single set ofGridBagConstraints, modify it as needed, and apply it as needed to different objects. You might want to create a helper method that sets the constraints appropriately, then adds the component with its con‐ straints to the layout. That’s the approach we’ll take in our examples; our helper method is called addGB(), and it takes a component plus a pair of coordinates as arguments. These coordinates become the gridx and gridy values for the constraints. We could expand upon this later and overload addGB() to take more parameters for other con‐ straints that we often change from component to component. Grid Coordinates One of the biggest surprises in the GridBagLayout is that there’s no way to specify the size of the grid. There doesn’t have to be. The grid size is determined implicitly by the constraints of all the objects; the layout manager picks dimensions large enough so that everything fits. Thus, if you put one component in a layout and set itsgridx andgridy constraints each to25, the layout manager creates a virtual 25 × 25 grid, with rows and columns numbered from 0 to 24. If you then add a second component with agridx of 30 and agridy of13, the virtual grid’s dimensions change to 30 × 25. You don’t have to worry about setting up an appropriate number of rows and columns. The layout man‐ ager does it automatically as you add components. With this knowledge, we’re ready to create some simple displays. We’ll start by arranging a group of components in a cross shape. We maintain explicit x and y local variables, setting them as we add the components to our grid. This is partly for clarity, but it can be a handy technique when you want to add a number of components in a row or column. You can simply incrementgridx orgridy before adding each component. This is a simple and problem-free way to achieve relative placement. (Later, we’ll describe GridBagConstraints’s RELATIVE constant, which performs relative placement auto‐ matically.) The following code shows the first layout (see Figure 19-7): //file: GridBag1.java import java.awt.; import java.awt.event.; import javax.swing.; public class GridBag1 extends JPanel GridBagConstraints constraints = new GridBagConstraints(); GridBagLayout 721 a public GridBag1() setLayout(new GridBagLayout()); int x, y; // for clarity addGB(new JButton("North"), x = 1, y = 0); addGB(new JButton("West"), x = 0, y = 1); addGB(new JButton("Center"), x = 1, y = 1); addGB(new JButton("East"), x = 2, y = 1); addGB(new JButton("South"), x = 1, y = 2); void addGB(Component component, int x, int y) constraints.gridx = x; constraints.gridy = y; add(component, constraints); public static void main(String args) JFrame frame = new JFrame("GridBag1"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(225, 150); frame.setLocation(200, 200); frame.setContentPane(new GridBag1()); frame.setVisible(true); Figure 19-7. A simple GridBagLayout The buttons in this example are “clumped” together in the center of their display area. Each button is displayed at its preferred size, without stretching to fill the available space. This is how the layout manager behaves when the “weight” constraints are left unset. We’ll talk more about weights in the next two sections. The fill Constraint Let’s make the buttons expand to fill the entireJFrame window. To do so, we must take two steps: we must set the fill constraint for each button to the value BOTH, and we must set theweightx andweighty to nonzero values, as shown in this example: 722 Chapter 19: Layout Managers a //file: GridBag2.java import java.awt.; import java.awt.event.; import javax.swing.; public class GridBag2 extends JPanel GridBagConstraints constraints = new GridBagConstraints(); public GridBag2() setLayout(new GridBagLayout()); constraints.weightx = 1.0; constraints.weighty = 1.0; constraints.fill = GridBagConstraints.BOTH; int x, y; // for clarity addGB(new JButton("North"), x = 1, y = 0); addGB(new JButton("West"), x = 0, y = 1); addGB(new JButton("Center"), x = 1, y = 1); addGB(new JButton("East"), x = 2, y = 1); addGB(new JButton("South"), x = 1, y = 2); void addGB(Component component, int x, int y) constraints.gridx = x; constraints.gridy = y; add(component, constraints); public static void main(String args) JFrame frame = new JFrame("GridBag2"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(225, 150); frame.setLocation(200, 200); frame.setContentPane(new GridBag2()); frame.setVisible(true); Figure 19-8 shows the resulting layout. Figure 19-8. Making buttons fill the available space GridBagLayout 723 a BOTH is one of the constants of theGridBagConstraints class; it tells the component to fill the available space in both directions. Here are the constants you can use to set the fill field: HORIZONTAL Fill the available horizontal space. VERTICAL Fill the available vertical space. BOTH Fill the available space in both directions. NONE Don’t fill the available space; display the component at its preferred size. We set the weight constraints to 1.0; in this example, it doesn’t matter what they are, provided each component has the same nonzero weight. Filling doesn’t occur if the component’s weight in the direction you’re filling is0, which is the default value. Spanning Rows and Columns One of the most important features ofGridBaglayout is that it lets you create arrange‐ ments in which components span two or more rows or columns. To do so, set the gridwidth and gridheight variables of the GridBagConstraints. The following ex‐ ample creates such a display; button one spans two columns vertically and button four spans two horizontally. Figure 19-9 shows the resulting layout. //file: GridBag3.java import java.awt.; import java.awt.event.; import javax.swing.; public class GridBag3 extends JPanel GridBagConstraints constraints = new GridBagConstraints(); public GridBag3() setLayout(new GridBagLayout()); constraints.weightx = 1.0; constraints.weighty = 1.0; constraints.fill = GridBagConstraints.BOTH; int x, y; // for clarity constraints.gridheight = 2; // span two rows addGB(new JButton("one"), x = 0, y = 0); constraints.gridheight = 1; // set it back addGB(new JButton("two"), x = 1, y = 0); addGB(new JButton("three"), x = 2, y = 0); constraints.gridwidth = 2; // span two columns addGB(new JButton("four"), x = 1, y = 1); constraints.gridwidth = 1; // set it back 724 Chapter 19: Layout Managers a void addGB(Component component, int x, int y) constraints.gridx = x; constraints.gridy = y; add(component, constraints); public static void main(String args) JFrame frame = new JFrame("GridBag3"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(200, 200); frame.setLocation(200, 200); frame.setContentPane(new GridBag3()); frame.setVisible(true); Figure 19-9. Making components span rows and columns The size of each element is controlled by the gridwidth and gridheight values of its constraints. For button one, we set gridheight to 2; therefore, it is two cells high. Its gridx andgridy positions are both0, so it occupies cell (0,0) and the cell directly below it, (0,1). Likewise, button four has agridwidth of2 and agridheight of1, so it occupies two cells horizontally. We place this button in cell (1,1), so it occupies that cell and its neighbor, (2,1). In this example, we set thefill toBOTH andweightx andweighty to1 for all compo‐ nents. By doing so, we tell each button to occupy all the space available and give them all equal weighting. Strictly speaking, this isn’t necessary. However, it makes it easier to see exactly how much space each button occupies. Weighting The weightx and weighty variables of a GridBagConstraints object determine how “extra” space in the container is distributed among the columns or rows in the layout. GridBagLayout 725 a As long as you keep things simple, the effect these variables have is fairly intuitive: the larger the weight, the greater the amount of space allocated to the component, relative to its peers. Figure 19-10 shows what happens if we vary the weightx constraint from 0.1 to1.0 as we place three buttons in a row. Here’s the code: //file: GridBag4.java import java.awt.; import java.awt.event.; import javax.swing.; public class GridBag4 extends JPanel GridBagConstraints constraints = new GridBagConstraints(); public GridBag4() setLayout(new GridBagLayout()); constraints.fill = GridBagConstraints.BOTH; constraints.weighty = 1.0; int x, y; // for clarity constraints.weightx = 0.1; addGB(new JButton("one"), x = 0, y = 0); constraints.weightx = 0.5; addGB(new JButton("two"), ++x, y); constraints.weightx = 1.0; addGB(new JButton("three"), ++x, y); void addGB(Component component, int x, int y) constraints.gridx = x; constraints.gridy = y; add(component, constraints); public static void main(String args) JFrame frame = new JFrame("GridBag4"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(300, 100); frame.setLocation(200, 200); frame.setContentPane(new GridBag4()); frame.setVisible(true); Figure 19-10. Using weight to control component size 726 Chapter 19: Layout Managers a The specific values of the weights are not meaningful; it is only their relative proportions that matter. After the preferred sizes of the components (including padding and insets— see the next section) are determined, any extra space is doled out in proportion to the component’s weights. For example, if each of our three components had the same weight, each would receive a third of the extra space. To make this more obvious, you may prefer to express the weights for a row or column as fractions totaling 1.0—for example: 0.25, 0.25, 0.50. Components with a weight of0 receive no extra space. The situation is a bit more complicated when there are multiple rows or columns and when there is even the possibility of components spanning more than one cell. In the general case, GridBagLayout calculates an effective overall weight for each row and column and then distributes the extra space to them proportionally. Note that the pre‐ vious single-row example is just a special case where the columns each have one com‐ ponent. The gory details of the calculations follow. Calculating the weights of rows and columns For a given row or column (“rank”), GridBagLayout first considers the weights of all the components contained strictly within that rank—ignoring those that span more than one cell. The greatest individual weight becomes the overall weight of the row or column. Intuitively, this means thatGridBagLayout is trying to accommodate the needs of the weightiest component in that rank. Next, GridBagLayout considers the components that occupy more than one cell and things get a little weird. GridbagLayout wants to evaluate them to see whether they affect the determination of the largest weight in a row or column. However, because these components occupy more than one cell, GridBagLayout divides their weight among the ranks (rows or columns) that they span. GridBagLayout tries to calculate an effective weight for the portion of the component that occupies each row or column. It does this by trying to divide the weight of the component among the ranks in the same proportions that the length (or height) of the component will be shared by the ranks. But how does it know what the proportions will be before the whole grid is determined? That’s what it’s trying to calculate, after all. It simply guesses based on the row or column weights already determined. GridBagLay out uses the weights determined by the first round of calculations to split up the weight of the component over the ranks that it occupies. For each row or column, it then considers that fraction of the weight to be the component’s weight for that rank. That weight then contends for the “heaviest weight” in the row or column, possibly changing the overall weight of that row or column, as we described earlier. GridBagLayout 727 aAnchoring If a component is smaller than the space available for it, it is centered by default. But centering isn’t the only possibility. Theanchor constraint tells a grid bag layout how to position a component within its cell in the grid. Possible values are GridBagCon straints.CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, and NORTHWEST. For example, an anchor of GridBagConstraints.NORTH centers a compo‐ nent at the top of its display area; SOUTHEAST places a component at the bottom-right corner of its area. Padding and Insets Another way to control the behavior of a component in a grid bag layout is to use padding and insets. Padding is determined by the ipadx and ipady fields of GridBagCon straints. They specify horizontal and vertical “growth factors” for the component. In Figure 19-11, the West button is larger because we have set theipadx andipady values of its constraints to 25. Therefore, the layout manager gets the button’s preferred size and adds 25 pixels in each direction to determine the button’s actual size. The sizes of the other buttons are unchanged because their padding is set to0 (the default), but their spacing is different. The West button is unnaturally tall, which means that the middle row of the layout must be taller than the others. //file: GridBag5.java import java.awt.; import java.awt.event.; import javax.swing.; public class GridBag5 extends JPanel GridBagConstraints constraints = new GridBagConstraints(); public GridBag5() setLayout(new GridBagLayout ()); int x, y; // for clarity addGB(new JButton("North"), x = 1, y = 0); constraints.ipadx = 25; // add padding constraints.ipady = 25; addGB(new JButton("West"), x = 0, y = 1); constraints.ipadx = 0; // remove padding constraints.ipady = 0; addGB(new JButton("Center"), x = 1, y = 1); addGB(new JButton("East"), x = 2, y = 1); addGB(new JButton("South"), x = 1, y = 2); void addGB(Component component, int x, int y) constraints.gridx = x; 728 Chapter 19: Layout Managers a