GridBagLayout 不会随着窗口的变化标签随之发生变化,可固定。
----------------------------------------------------------
import java.awt.Button;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GridBagEx2 extends JPanel
{
private static final long serialVersionUID = -5214441555967215113L;
protected void makebutton(String name, GridBagLayout gridbag,
GridBagConstraints c)
{
Button button = new Button(name);
gridbag.setConstraints(button, c);
add(button);
}
public void init()
{
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setFont(new Font("SansSerif", Font.PLAIN, 14));
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
makebutton("Button4", gridbag, c);
c.weightx = 0.0; //reset to the default
makebutton("Button5", gridbag, c); //another row
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row
makebutton("Button6", gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
makebutton("Button7", gridbag, c);
c.gridwidth = 1; //reset to the default
c.gridheight = 2;
c.weighty = 1.0;
makebutton("Button8", gridbag, c);
c.weighty = 0.0; //reset to the default
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.gridheight = 1; //reset to the default
makebutton("Button9", gridbag, c);
makebutton("Button10", gridbag, c);
setSize(300, 100);
}
public static void main(String args[])
{
JFrame f = new JFrame("GridBag Layout Example");
f.setLocation(400, 200);
GridBagEx2 ex1 = new GridBagEx2();
ex1.init();
f.add("Center", ex1);
f.pack();
f.setSize(f.getPreferredSize());
f.setVisible(true);
f.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
}
The Java AWT: GridBagLayout
Jan Newmarch
Web:
http://jan.newmarch.name
Email:
jan@newmarch.name
Contents
- Introduction
- Debugging
- GridBagConstraints
- Absolute positioning
- Cell sizes
- Relative positioning
- Filling
- Anchor
- Padding and Insets
- Spanning multiple cells
- Relatively ending rows and columns
- Weight
- Limitations and variations
- Conclusion
Introduction
A graphical user interface is built up in Java by adding objects
to Container
s, and using LayoutManager
s
to place and size them within the containers.
There are several managers supplied in AWT:
-
BorderLayout
- NSEW layout -
FlowLayout
- left-to-right with overflow -
GridLayout
- regular rectangular grid -
GridBagLayout
- general gridded layout -
CardLayout
- allows "flipping" through a set of "cards"
In the last issue of the X Advisor I discussed all of these
except for GridBagLayout
. The reason is simple:
GridBagLayout
is a manager that
can layout a large number of configurations in a flexible way.
This ability comes through complexity, and there is a lot to learn
before you can use this manager effectively. This article is devoted
entirely to GridBagLayout
.
GridBagLayout
is used to place objects in a rectangular
grid. The cells of this grid need not be the same size, and the objects
can span several cells. There is control over placement of each object
within the space allowed for it, and how it fills this space.
Debugging
The more complex the layout manager, the harder it is to get
layouts correct. Under X, I use two techniques to help me with
layouts using this manager. The first is very specifically
X Oriented: set the resource borderWidth
for all
objects to some non-zero value. Then you can see exactly
how each object is placed, including objects like labels
which don't normally have visible edges. I set this in
.Xdefaults
:
*borderWidth: 3
The second technique is more generally applicable, but harder to interpret. GridBagLayout
has two protected
methods, DumpConstraints()
and DumpLayoutInfo()
, intended for debugging the manager itself. However, if you want access to this level of information then you can subclass the manager and call these methods yourself. Here is a suitable subclass. Note that it must be installed in $CLASSES/java/awt since it has to belong to package java.awt
package java.awt; public class DebugGridBagLayout extends GridBagLayout { public void dumpLayoutInfo(Container parent) { GridBagLayoutInfo s = GetLayoutInfo(parent, GridBagLayout.PREFERREDSIZE); DumpLayoutInfo(s); } public void dumpConstraints(Container parent) { Component comp; GridBagConstraints constraints; for (int n = 0; n < parent.ncomponents; n++) { comp = parent.getComponent(n); constraints = lookupConstraints(comp); DumpConstraints(constraints); } } }
Not all problems with using this manager are caused by your bugs :-). Many of the applets that run within this article fail to show components when they begin execution. Partly for this reason, I use components such as Button
that respond to inputs and redraw themselves on changes. If some of the applets seem to be missing components, click over them to show the missing ones.
On my system, at least one of the applets displays correctly using appletviewer
but doesn't show under Netscape 2.0.
GridBagConstraints
In order to layout objects within a container, the manager needs to know some information about them. A very simple manager like FlowLayout
just needs to know the order in which objects were added to the container and it can get this from the container itself. A manager like BorderLayout
needs to associate objects with special positions such as "North", and it gets this association from the add(String, Component)
method. When the container executes this it also calls the layout object's addLayoutComponent(String, Component)
which allows the layout manager to store information.
The information needed by GridBagLayout
for each object is complicated: direction of layout, number of cells spanned, placement within this space, etc. The above methods are too simple for that. Instead, all of this information is stored in a GridBagConstraints
object, and this is passed through to the layout manager by
setConstraints(Component, GridBagConstraints)
The layout manager makes a copy of the GridBagConstraints
and links it to the Component
using a hash table. (This means that you only need to have one of these objects which you can reset values of without messing up earlier references.)
Typical code using this manager is
GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); // set values in constraints ... Button btn = new Button("Hello"); add(btn); // tell the layout manager of the constraints gridbag.setConstraints(btn, constraints);
The fields of GridBagConstraints
are
public int gridx, gridy, gridwidth, gridheight; public double weightx, weighty; public int anchor, fill; public Insets insets; public int ipadx, ipady;
These may be set by an application. They are discussed in the article in the appropriate places.
Absolute positioning
The two fields gridx
and gridy
may be used to set the positions of objects, where the topleft cell is at (0, 0). For example, to arrange four buttons at the corners of a fifth,
import java.awt.*; public class Absolute extends Frame { public static void main(String argv[]) { new Absolute().show(); } public Absolute() { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); Button btn1 = new Button("Button 1"); add(btn1); // set at (0,0) constraints.gridx = 0; constraints.gridy = 0; gridbag.setConstraints(btn1, constraints); Button btn2 = new Button("Button 2"); add(btn2); // set at (2,0) constraints.gridx = 2; constraints.gridy = 0; gridbag.setConstraints(btn2, constraints); Button btn3 = new Button("Button 3"); add(btn3); // set at (0,2) constraints.gridx = 0; constraints.gridy = 2; gridbag.setConstraints(btn3, constraints); Button btn4 = new Button("Button 4"); add(btn4); // set at (2,2) constraints.gridx = 2; constraints.gridy = 2; gridbag.setConstraints(btn4, constraints); Button btn5 = new Button("Button 5"); add(btn5); // set at (1,1) constraints.gridx = 1; constraints.gridy = 1; gridbag.setConstraints(btn5, constraints); resize(300, 300); } }
The program looks like
Note that problems in the AWT may result in buttons not showing until
pressed. It should look like
Cell sizes
The manager displays objects in one or more cells. The cells may be of different sizes. In each row the cells all have the same height, though, and in each column the cells all have the same width.
For each row, the height is calculated by looking at the
preferredSize().height
of the components in
that row. The maximum of these is found, and then the value of
ipady
is added twice (for top and bottom).
The height is usually this, unless made larger by some other
constraint. Whatever,
the height of the row cannot be smaller than this.
Similarly, the width of each column is not smaller than the
maximum preferred width of each component,
plus twice ipadx
.
Different rows can thus have different heights, and different columns
can have different widths. To see this, replace one of the
buttons by, say, a TextArea
:
The sizing policy means that if there is nothing
in a row and ipady
is also zero, then the row has no width and does not show.
Similarly with a column with no components. In the example program
if we remove the central button, "Button 5", then that row and
column have zero height and width respectively, and all four
buttons show up against each other.
if you want to get four buttons occupying corners with a middle space,
then you need to adjust ipadx
and ipady
to leave space around each button. This would leave a border around
the outside though. This particular problem is revisited later.
REVISIT THIS.
In the JDK version 1.0, there is a limitation on the number of
components that can appear in any row or column. Each is set to
a maximum of 128. If you exceed this, then an
ArrayIndexOutOfBoundsException
is raised.
Relative positioning
If you want to layout a lot of objects in a row, then having to
specify gridx
for each of them may be a little tedious.
An alternative way is to use relative positioning, in which
you say how to layout a component with respect to the last one
(roughly). The fields gridx
and gridy
are
used for this relative placement as well as the absolute placement.
If gridx == RELATIVE
then add in row order. That is,
place the next component to the right of the previous component
unless the previous component was the last in the row,
in which case this one starts a new row.
Similarly, if gridy == RELATIVE
then add in column
order. That is, add below the previous component unless it was the
last in the column, in which case it is placed in a new column to the right.
If both gridx
and gridy
are RELATIVE
then add in row order. This is the default value for a
GridBagConstraints
object.
These values can be reset for each component.
It is also possible to mix up the absolute and relative
styles of positioning together.
A simple example of relative positioning is to set a group of buttons
vertically without having to reset the GridBagConstraints
each time (this is, of course, easier with GridLayout
)
import java.awt.*; public class Vertical extends Frame { public static void main(String argv[]) { new Vertical().show(); } public Vertical() { Button btn; GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; // note: gridy == RELATIVE for (int n = 1; n <= 8; n++) { btn = new Button("Button " + n); add(btn); gridbag.setConstraints(btn, constraints); } } }
which shows as
More complex arrangements can be obtained by mixing relative and absolute positioning:
import java.awt.*; public class Direction extends Frame { Button btn1, btn2, btn3, btn4, btn5, btn6; GridBagLayout gridbag; GridBagConstraints c; public static void main(String argv[]) { new Direction().show(); } void makeButtons() { btn1 = new Button("Button 1"); add(btn1); btn2 = new Button("Button 2"); add(btn2); btn3 = new Button("Button 3"); add(btn3); btn4 = new Button("Button 4"); add(btn4); btn5 = new Button("Button 5"); add(btn5); btn6 = new Button("Button 6"); add(btn6); } public Direction() { gridbag = new GridBagLayout(); setLayout(gridbag); c = new GridBagConstraints(); makeButtons(); // use defaults for btn1 gridbag.setConstraints(btn1, c); // btn2 below btn1 c.gridx = 0; // gridy is still RELATIVE gridbag.setConstraints(btn2, c); // btn3 below of btn2 - reuse constraint gridbag.setConstraints(btn3, c); // btn4 right of btn2 c.gridx = GridBagConstraints.RELATIVE; c.gridy = 1; gridbag.setConstraints(btn4, c); // btn5 right of btn4 c.gridx = GridBagConstraints.RELATIVE; c.gridy = 2; gridbag.setConstraints(btn5, c); // btn6 down and to right of btn5 c.gridx = 2; c.gridy = 3; gridbag.setConstraints(btn6, c); resize(400, 200); } }
which shows as
Filling
When a component is placed in a cell, the cell is guaranteed to be
at least as large as the component plus twice the values of
ipadx
and ipady
.
If there are components of different sizes then some of them will
be smaller than the cell size.
A component may also be set to occupy more than one cell,
which it may not be large enough to fill.
The amount of space an object occupies within its allocated area
is controlled by the fill
field of the constraints
object. The possible values are
-
HORIZONTAL
- set the component's width to the full size available. -
VERTICAL
- set the component's height to the full size available. -
BOTH
- set the width and height to the size of the available space.
Anchor
There is an additional method of control over placement of an object
when its preferred size is smaller than that of the space it has to
occupy. The anchor
field controls location within this.
The possible values of this are
NORTH
, NORTHEAST
, EAST
,
SOUTHEAST
, SOUTH
, SOUTHWEST
,
WEST
, NORTHWEST
and (the default)
CENTER
.
The following example is quite artificial: it forces a space larger
than a normal Button
by setting a long TextField
horizontally and a high TextArea
vertically.
A Button
is set in this because it has natural edges so you
can see what happens to its boundaries. The applet allows selection
of fill
and anchor
parameters and how
they affect the Button
. The source contains several uses
of layout managers and is available as
FillAnchorApplet.java
(Note: setting the anchor
has no effect until a change is
made to fill
- another minor bug in AWT :-( ).
Padding and Insets
There is a third level of control over sizing and placement of objects
(just for variety :-( ). Each GridBagConstraint
has fields
of ipadx
, ipady
and insets
-
an Insets
object.
The insets
object acts like it does in other managers.
Given a space in which to locate an object, insets
specifies
a top
, bottom
, left
and
right
restriction of this space. So with a top
value of, say, 10, the top of the object must appear 10 pixels down
from the top of the space.
The ipadx
and ipady
fields specify internal
padding i.e. space that is added to the object's size to find
its "real" size. With an ipadx
of 20 pixels, the object
will be 40 pixels (20 for each side) wider than otherwise.
The difference can be seen by the following applet. It sets up five
buttons vertically. Buttons 1, 3 and 5 all have constraints with
ipadx = ipday = 0
, and insets
with all
fields zero. Button 2 sets its ipady
to 20, and so is
40 pixels taller than normal. Button 4 sets insets.top = 20
and insets.bottom = 50
, meaning that the
height it requires is 70 pixels taller than the space it displays in.
import java.awt.*; import java.applet.*; public class PaddingApplet extends Applet { public PaddingApplet() { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); Button btn1 = new Button("Button 1"); add(btn1); constraints.gridx = 0; // add in column order gridbag.setConstraints(btn1, constraints); Button btn2 = new Button("Button 2"); add(btn2); constraints.ipady = 20; gridbag.setConstraints(btn2, constraints); Button btn3 = new Button("Button 3"); add(btn3); constraints.ipady = 0; // reset to default gridbag.setConstraints(btn3, constraints); Button btn4 = new Button("Button 4"); add(btn4); constraints.insets.top = 20; constraints.insets.bottom = 50; gridbag.setConstraints(btn4, constraints); Button btn5 = new Button("Button 5"); add(btn5); constraints.insets.top = 0; // reset to default constraints.insets.bottom = 0; // reset to default gridbag.setConstraints(btn5, constraints); resize(300, 300); } }
The program looks like
This mechanism allows us to solve the problem posed earlier in
"Cell sizes": in the Absolute.java
five buttons were
shown with corners touching. Remove the center one and the arrangement
collapses to the remaining four in a 2x2 grid. The middle row and
column have height and width set to zero, respectively, and don't show.
To preserve the spacing of these four can be done by setting them in a
2x2 grid but setting insets
to force them apart.
If we want to set the four objects with a fixed space
apart, then we can do that by just changing earlier programs to set
an Insets
object. If we want to set the space to between
the four objects to the preferred size (or something related
to preferred or minimum sizes) then it gets a bit trickier.
This warrants a "sidebar" discussion, so here is an inline version:
Diversion: widget creation
Methods such as preferredSize()
rely on the native
implementation. If the native code object has not yet been created
then such methods return "sensible" values such as
Dimension(0, 0)
.
The native code objects are created by peer
methods
such as createButton()
. These are called by a GUI
object's method addNotify()
.
When a container calls layout()
the native object has
already been created, so it can do meaningful geometry calculations.
If we want to find meaningful values for preferredSize()
before this, then we have to ensure that the native object has already
been created. So far, we have been relying on show()
to do this.
The Window
method pack()
is documented as
"packs the components of the Window". It actually does something
far more important than that: it calls addNotify()
on itself and on all of its children. This creates the peer
objects and the native implementation. From then on, whenever a
container method add()
is executed, it also calls
addNotify()
on the component.
To be able to find the preferred/minimum size of an object before
show()
is executed, call pack()
on the
toplevel Window
(or Frame
), and then
add()
each component. Then geometry works.
(For applets, packing has been done by the time the init()
method is called.)
End diversion
To creae a "hole" that is made from the preferred size of the
surrounding objects, first call pack()
on the
Window
and then add()
each component.
After that it is valid to ask for preferred sizes and set this in the
Insets
constraint field:
import java.awt.*; public class AbsoluteHole extends Frame { public static void main(String argv[]) { new AbsoluteHole().show(); } public AbsoluteHole() { // here is the pack() pack(); // then add the rest setContents(); } void setContents() { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); // Button 1 Button btn1 = new Button("Button 1"); add(btn1); constraints.gridx = 0; constraints.gridy = 0; Dimension size = btn1.preferredSize(); constraints.insets = new Insets(0, 0, // top, left size.height/2, // bottom size.width/2); // right gridbag.setConstraints(btn1, constraints); // Button 2 Button btn2 = new Button("Button 2"); add(btn2); constraints.gridx = 1; constraints.gridy = 0; size = btn2.preferredSize(); constraints.insets = new Insets(0, // top size.width/2, // left size.height/2, //bottom 0); gridbag.setConstraints(btn2, constraints); // Button 3 Button btn3 = new Button("Button 3"); add(btn3); constraints.gridx = 0; constraints.gridy = 1; size = btn3.preferredSize(); constraints.insets = new Insets(size.height/2, // top 0, 0, //left, bottom size.width/2); // right gridbag.setConstraints(btn3, constraints); // Button 4 Button btn4 = new Button("Button 4"); add(btn4); constraints.gridx = 1; constraints.gridy = 1; size = btn4.preferredSize(); constraints.insets = new Insets(size.height/2, //top size.width/2, //left 0, 0); // bottom, right gridbag.setConstraints(btn4, constraints); resize(300, 300); } }
Spanning multiple cells
The GridBagConstraints
fields gridwidth
and gridheight
are used to specify how many cells
a component should span in that direction.
For example, the following applet places three buttons in a row along
the top, three down the left, with another button occupying the
remaining 2x2 space:
import java.awt.*; import java.applet.*; public class BigButtonApplet extends Applet { Button btn1, btn2, btn3, btn4, btn5, btn6; GridBagLayout gridbag; GridBagConstraints c; void makeButtons() { btn1 = new Button("Button 1"); add(btn1); btn2 = new Button("Button 2"); add(btn2); btn3 = new Button("Button 3"); add(btn3); btn4 = new Button("Button 4"); add(btn4); btn5 = new Button("Button 5"); add(btn5); btn6 = new Button("Button 6"); add(btn6); } public BigButtonApplet() { gridbag = new GridBagLayout(); setLayout(gridbag); c = new GridBagConstraints(); makeButtons(); gridbag.setConstraints(btn1, c); c.gridx = 1; c.gridy = 0; gridbag.setConstraints(btn2, c); c.gridx = 2; c.gridy = 0; gridbag.setConstraints(btn3, c); c.gridx = 0; c.gridy = 1; gridbag.setConstraints(btn4, c); c.gridx = 0; c.gridy = 2; gridbag.setConstraints(btn5, c); c.gridx = 1; c.gridy = 1; c.gridwidth = 2; c.gridheight = 2; c.fill = GridBagConstraints.BOTH; gridbag.setConstraints(btn6, c); } }
The program looks like
Note that Button 6
would normally be smaller than the space
it is allocated, so fill
is set to BOTH
to
force it to fill all of this space.
Relatively ending rows and colums
With relative placement of components, you can add components to the
right of or below the previous component. There is also a mechanism within
GridBagConstraints
to allow the end of a row,
or the bottom of a column to be specified. Setting
gridWidth
to REMAINDER
makes this component
the last in a row, whereas setting gridHeight
to
REMAINDER
makes this the last in a column.
The more I use this manager, the less I use this method. It seems much easier to use absolute positioning.
Setting gridWidth
to RELATIVE
makes this
component the last but one in this row. Similarly, setting
gridHeight
to RELATIVE
makes this component
the last but one in its column. I have never used this this.
The possibilities for specifying inconsistent geometry seem to
explode with this method!
Weight
The discussion so far has been in terms of placing components within
cells. The size of a cell is calculated as not smaller than the
biggest object that must fit inside it. When an object occupies a
space larger than its preferred size, then the fill
attribute specifies how it fills this space.
There may be external constraints that act on sizes. For example,
the container with a GridBagLayout
may be managed
by another layout manager such as GridLayout
that forces
the size of this container. How are these external size requests
passed to the components?
For example, in the last article we looked at aLabelledTextField
,
where a Label
was put to the left of a TextField
.
The constraints on sizes were that the Label
was kept
at a constant size (the width of the text) whereas the TextField
would stretch to fill the remaining space. This was done using a
BorderLayout
manager, but should be (and can be) also
done with GridBagLayout
.
The fields weightx
and weighty
control how
the manager resizes the components in response to external constraints.
A weight of 0.0 means no external resizing is done. This is the
default value.
In the earlier examples, the default value was used, so the externally set size of the container was ignored. What the layout manager does in this case is to use its own internal calculations, and then place the group of objects in the center of its space.
If we specify an object to have a weight of more than zero in a
direction then the manager can resize the object to fill its available
space. To take the LabelledTextField
example, here
is an implementation using GridBagLayout
:
import java.awt.*; public class LabelledTextField extends Panel { Label label; TextField text; public LabelledTextField(String l, int cols) { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); label = new Label(l); text = new TextField(cols); add(label); add(text); // set resizing gridbag.setConstraints(label, constraints); constraints.weightx = 1.0; constraints.fill = GridBagConstraints.HORIZONTAL; gridbag.setConstraints(text, constraints); } public String getText() { return text.getText(); } }
Using this within a program looks like
Each component in a layout can have its own widthx
and widthy
. However, when it comes to laying out the
components the cells in any row will all be the same size, and the
cells in any column will all be the same size. So GridBagLayout
needs to calculate row weights and column weights.
It finds a row weight by taking the maximum value of all the x-weights
in the row, and the column weight as the maximum of all the y-weights
for that column.
If there is more than one column and at least one of these has a non-zero
weight, then any extra space will need to be distributed. The following
example has three columns with weightx
respectively of
1, 2 and 4.
import java.awt.*; public class Weight extends Frame { public static void main(String argv[]) { new Weight().show(); } public Weight() { GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints constraints = new GridBagConstraints(); Button btn1 = new Button("Button 1"); add(btn1); constraints.weightx = 1; constraints.fill = GridBagConstraints.BOTH; gridbag.setConstraints(btn1, constraints); Button btn2 = new Button("Button 2"); add(btn2); constraints.weightx = 2; gridbag.setConstraints(btn2, constraints); Button btn3 = new Button("Button 3"); add(btn3); constraints.weightx = 4; gridbag.setConstraints(btn3, constraints); resize(300, 100); } }
GridbagLayout
distributes the extra space in proportion to the weights. To make this more concrete, suppose the preferred width of each button is 10 pixels, and the actual width available is 65 pixels. Then there are 65-30 = 35 pixels spare. The total weight of the row is 1+2+4 = 7. So Button 1 gets 1/7 of 35 i.e. 5 extra pixels to bring its width to 10+5 = 15 pixels. Button 2 gets 2/7 of 35 to bring its width to 10+10 = 20 pixels, and Button 3 gets 4/7 of 35 to bring its width to 10+20 = 30 pixels.
To observe this resizing behaviour, the following applet (similar to the applets in the last article) may be used if you are running a Java-aware browser:
Limitations and variations
We have already mentioned that if a row contains no elements then
its height is zero and nothing shows. There are other limitations
as well. One other that I have come across is in trying to set a
gridWidth
or gridHeight
that is too large.
For example, if only one row is specified but a request is made for
a height of two, then it will be shown with a height of only one.
Layouts may display very differently with only a minor change in code.
The following three layouts show versions that differ
in small ways.
In the first layout weightx
and fill
use default values.
In the second layout weightx
is set to 1.0.
In the third layout weightx
is set to 1.0 and
fill
to HORIZONTAL
.
Conclusion
This article has discussed the GridBagLayout
manager
in depth. The manager allows a tremendous amount of freedom to build
complex arrangements. However it is not easy to learn, and a large
amount of time will be needed to determine the best way to layout
any complex arrangement.
The next article in this series will probably be on dialogs. Some possibilities for other articles include designing layouts, menus, applets vs applications, the new event model, adding native widgets, interacting with the window manager or browser, and images. In the previous articles I have been choosing topics on what I found lacking in the existing documentation, so if you have any preferences, or other topics that you wish discussed let me know in the article evaluation comments. Thanks!