Controlling layout

Bruce Eckel’s Thinking in Java Contents | Prev | Next

FlowLayout

//: FlowLayout1.java
// Demonstrating the FlowLayout
import java.awt.*;
import java.applet.*;
 
public class FlowLayout1 extends Applet {
  public void init() {
    setLayout(new FlowLayout());
    for(int i = 0; i < 20; i++)
      add(new Button("Button " + i));
  }
} ///:~ 

All
components will be compacted to their smallest size in a
FlowLayout,
so you might get a little bit of surprising behavior. For example, a label will
be the size of its string, so right-justifying it yields an unchanged display.

BorderLayout

Here’s
a simple example:

//: BorderLayout1.java
// Demonstrating the BorderLayout
import java.awt.*;
import java.applet.*;
 
public class BorderLayout1 extends Applet {
  public void init() {
    int i = 0;
    setLayout(new BorderLayout());
    add("North", new Button("Button " + i++));
    add("South", new Button("Button " + i++));
    add("East", new Button("Button " + i++));
    add("West", new Button("Button " + i++));
    add("Center", new Button("Button " + i++));
  }
} ///:~ 

For
every placement but “Center,” the element that you add is
compressed to fit in the smallest amount of space along one dimension while it
is stretched to the maximum along the other dimension. “Center,”
however, spreads out along both dimensions to occupy the middle.

The
BorderLayout
is the default layout manager for applications and dialogs.

GridLayout

//: GridLayout1.java
// Demonstrating the FlowLayout
import java.awt.*;
import java.applet.*;
 
public class GridLayout1 extends Applet {
  public void init() {
    setLayout(new GridLayout(7,3));
    for(int i = 0; i < 20; i++)
      add(new Button("Button " + i));
  }
} ///:~ 

In
this case there are 21 slots but only 20 buttons. The last slot is left empty;
no “balancing” goes on with a
GridLayout.

CardLayout


Combining
layouts

//: CardLayout1.java
// Demonstrating the CardLayout
import java.awt.*;
import java.applet.Applet;
 
class ButtonPanel extends Panel {
  ButtonPanel(String id) {
    setLayout(new BorderLayout());
    add("Center", new Button(id));
  }
}
 
public class CardLayout1 extends Applet {
  Button
    first = new Button("First"),
    second = new Button("Second"),
    third = new Button("Third");
  Panel cards = new Panel();
  CardLayout cl = new CardLayout();
  public void init() {
    setLayout(new BorderLayout());
    Panel p = new Panel();
    p.setLayout(new FlowLayout());
    p.add(first);
    p.add(second);
    p.add(third);
    add("North", p);
    cards.setLayout(cl);
    cards.add("First card",
      new ButtonPanel("The first one"));
    cards.add("Second card",
      new ButtonPanel("The second one"));
    cards.add("Third card",
      new ButtonPanel("The third one"));
    add("Center", cards);
  }
  public boolean action(Event evt, Object arg) {
    if (evt.target.equals(first)) {
      cl.first(cards);
    }
    else if (evt.target.equals(second)) {
      cl.first(cards);
      cl.next(cards);
    }
    else if (evt.target.equals(third)) {
      cl.last(cards);
    }
    else
      return super.action(evt, arg);
    return true;
  }
} ///:~ 

This
example begins by creating a new kind of
Panel:
a
ButtonPanel.
This contains a single button, placed at the center of a
BorderLayout,
which means that it will expand to fill the entire panel. The label on the
button will let you know which panel you’re on in the
CardLayout.

In
the applet, both the
Panel
cards

where the cards will live and the layout manager
cl
for the
CardLayout
must be members of the class because you need to have access to those handles
when you want to manipulate the cards.

The
applet is changed to use a
BorderLayout
instead of its default
FlowLayout,
a
Panel
is created to hold three buttons (using a
FlowLayout),
and this panel is placed at the “North” end of the applet. The
cards
panel is added to the “Center” of the applet, effectively occupying
the rest of the real estate.

When
you add the
ButtonPanels
(or whatever other components you want) to the panel of cards, the
add( )
method’s first argument is not “North,” “South,”
etc. Instead, it’s a string that describes the card. Although this string
doesn’t show up anywhere on the card, you can use it if you want to flip
that card using the string. This approach is not used in
action( );
instead the
first( ),
next( ),
and
last( )
methods are used. Check your documentation for the other approach.

In
Java, the use of some sort of “tabbed panel” mechanism is quite
important because (as you’ll see later) in applet programming the use of
pop-up dialogs is heavily discouraged. For Java 1.0
applets, the
CardLayout
is the only viable way for the applet to have a number of different forms that
“pop up” on command.

GridBagLayout

Some
time ago, it was believed that all the stars, planets, the sun, and the moon
revolved around the earth. It seemed intuitive from observation. But then
astronomers became more sophisticated and started tracking the motion of
individual objects, some of which seemed at times to go backward in their
paths. Since it was known that everything revolved around the earth, those
astronomers spent large amounts of time coming up with equations and theories
to explain the motion of the stellar objects.

My
recommendation is to avoid
GridBagLayout.
Instead, use the other layout managers and especially the technique of
combining several panels using different layout managers within a single
program. Your applets won’t look
that
different; at least not enough to justify the trouble that
GridBagLayout
entails. For my part, it’s just too painful to come up with an example
for this (and I wouldn’t want to encourage this kind of library design).
Instead, I’ll refer you to
Core
Java

by Cornell & Horstmann (2
nd
ed., Prentice-Hall, 1997) to get started.

More by Author

Must Read