Whizbang programs in Java or any other language are all well and good but without a friendly and responsive user interface, that program is about as useful to the average user as so much burnt coffee grounds. If it is also attractive, so much the better! To help the programmer build a better user interface, Java provides five "layout managers" that dictate where each component (they used to be called a "widget") is placed on the container. The layout manager is specified for each container (often a Panel) in the "init" or "constructor" method.
FlowLayout is the default if no other is specified. This layout simply places components one after the other sequentially, left to right. GridLayout lets you place components in rows and columns, left to right, top to bottom, with each cell of the grid being the same size. BorderLayout is still simple but offers more placement control. It provides four cells around the edges (North, South, East, and West) plus a Center. Scrollbars can be placed at the edges with other components in the center. CardLayout is like a deck of tabbed cards where only one card shows at a time. Lastly, GridBagLayout provides a great deal of control over component placement and size. The theory is that when using GridBagLayout, you can place a component anywhere you so desire. Nice theory but not easy to actually accomplish.
GridBagLayout is the most flexible Layout Manager but it will also most likely give you the most headaches. Still, once you master it, or at least make an uneasy truce with it, you will find there is no substitute. GridBagLayout uses the basic concept of GridLayout (rows and columns) but with each cell in a column the same size. In addition, it lets you tell it in which cell to place the component, using xy coordinates, and how many cells the component should cover. Thus, it places components according to your specific directions. You provide these directions by setting the GridBagConstraints (java.awt.GridBagConstraints class). It is usually very useful to place the setting of these constraints into a method with the parameters being the public instance variables of the Constraints class, or at least those you are using most often. If you do not provide specific constraints, the layout manager doesn't know what to do so the components will be lumped all together in the middle of the panel! Probably not what you want. If you are not careful in setting the Constraints, components will be overlapped or seem to not be there at all. Drawing a picture on grid paper of what you want can be helpful.
There are eleven public instance variables you can set for each component placed on the Panel. Here are the 11:
anchor: where the component is placed inside a cell (a geographical direction, e.g.NORTHWEST)fill: how a component should grow when the window is resized (HORIZONTAL,VERTICAL,BOTH,NONE; default:NONE)gridheight: height of the component in number of cellsgridwidth: width of the component in number of cells (useREMAINDERfor the last component)gridx: grid position of the component, x coordinategridy: grid position of the component, y coordinate (RELATIVE: component to the right or below the last component)insets: margins around the cellipadx: margins inside the cell, around the componentipady: margins inside the cell, around the component (internal padding)weightx: how much a component should grow when the window is resizedweighty: how much a component should grow when the window is resized (0: no growth, 1: all extra space)
gridx and gridy are perhaps most commonly set for each component after initialization of all the constraints. These two tell the layout manager where the component is to be placed on the panel. The next two most used constraints are probably gridheight and gridwidth which say how many cells you want the component to cover. Note that if the "fill" constraint is not set, the component will not grow despite what you may set for gridwidth and gridheight. Setting the "fill" constraint once for all components gives a uniform look to the components but you may prefer to set it for each component individually or for small groups of components.
Once the constraint values are set for a particular component, the method setConstraints must be called with that component as the first parameter and the constraints variable as the second.Then the component is added to the container. After all components have been constrained and added, the method setConstraints must be called once more, this time with the container holding all those components as the first parameter (and still the constraints variable as the second). Finally, the container itself is added and the whole thing is validated.
Here is an example applet of several buttons for you to try. Play with the numbers in the calls to setPosConstraints to see what happens. In this way, you will get a better understanding of how the GridBagLayout and its constraints work.
<!-- This is the HTML code --> <CENTER> <TABLE BORDER=5 CELLPADDING=10 CELLSPACING=3> <tr> <th COLSPAN=3><font size="6"> MokaByte Examples </font></th> </tr> <tr> <td align="right"> October </td> <td> <APPLET CODEBASE="./" <!_ change this to your location _> CODE="gblExample.class" WIDTH=300 HEIGHT=200> </APPLET> </td> </tr> </TABLE> </CENTER>
// the Java example: gridBagLayout usage
import java.awt.*;
import java.applet.*;
public class gblExample extends java.applet.Applet{
public static final String fontNameTR = "TimesRoman";
public static final int fontSize = 14;
public static final int fontStyleP = Font.PLAIN;
GridBagLayout gbLyt = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
Panel aPnl = new Panel();
Button joButn = new Button("JavaOne");
Button fmButn = new Button("FortMason");
Button tfbButn = new Button("Top Floor Bar");
Button lcButn = new Button("Lost Car");
Button hoButn = new Button("Handouts");
Button rxButn = new Button("Rex");
Button sfButn = new Button("SanFrancisco");
// Method: init
public void init() {
Font f = new Font(fontNameTR, fontStyleP, fontSize);
setFont(f);
aPnl.setLayout(gbLyt);
setBaseConstraints(aPnl, c);
// set Positional Constraints:
/*setPosConstraints parameters (container, component,
constraints, gridx,
gridy, gridwidth, gridheight,
weightx, weighty)
*/
joButn.setFont(new Font(fontNameTR, Font.BOLD, fontSize+2));
// x y w h weight
setPosConstraints(aPnl, joButn, c, 0, 0,1, 1, 0, 0);
setPosConstraints(aPnl, lcButn, c, 1, 0, GridBagConstraints.REMAINDER,1, 1, 1);
setPosConstraints(aPnl, sfButn, c, 0, 1, 2, 1, 1, 1);
setPosConstraints(aPnl,rxButn, c, 2, 1, 1, 2, 1, 1);
setPosConstraints(aPnl, fmButn, c, 0, 2,1, 2, 1, 1);
setPosConstraints(aPnl, hoButn, c, 1, 2, 1, 1, 1, 1);
setPosConstraints(aPnl,tfbButn, c, 1, 3, 2, 1, 1, 1);
// finish up
add(aPnl);
validate();
}
// end init
// Method: setPosConstraints: set positional constraints for given panel
public void setPosConstraints(Container cntnr, Component widget,
GridBagConstraints c, int gx, int gy, int gwd,int ght, int wtx, int wty) {
c.gridx = gx;
c.gridy = gy;
c.gridwidth =gwd;
c.gridheight = ght;
c.weightx = wtx;
c.weighty = wty;
gbLyt.setConstraints(widget,c);
cntnr.add(widget);
}
// end setPosConstraints
// Method: setBaseConstraints
// set basic constraints for given panel
public void setBaseConstraints(Panel pnl, GridBagConstraints c) {
c.fill = GridBagConstraints.BOTH;
c.ipadx= 1;
c.ipady = 1;
c.insets = new Insets(2, 2, 2, 2);
c.anchor = GridBagConstraints.NORTHWEST;
gbLyt.setConstraints(pnl, c);
}
// end setBaseConstraints
// Method: insets make spacing between items
public Insets insets() {
return new Insets(2,2, 2, 2);
}
}
// end gblExample
Well, that's a start with GridBagLayout. Gaining experience with the various constraints settings and their interactions will help you to set up really killer web pages. Mail me any comments you may have about this or with suggestions for future topics (aalm@bayarea.net).
In the words of Scott McNealy: Go Java!
Ecco qui di seguito il risultato che si ottiene con l'applet descritto da Marie
MokaByte Examples October
