Week 11 - March 30, 1999
Designing the GUI layout
As you have seen in the previous example, if you keep adding controls to
the applet, they are added sequentially, one after another. This is not
useful when you need to design a nice interface with a certain number of
controls and a given layout. In order to create such an interface, one
has to use the LayoutManager. This is the hidden tool that allows
a Java developer to better organize the controls of the GUI. The LayoutManager
uses couple of predefine layout models which are included in the JDK. It
can also use different layout models created by other developers, one of
which is the PackerLayout. Let' take a look first at the built-in
models.
BorderLayout
This class implements the LayoutManager interface to lay out component
objects. The BorderLayout arranges components that have been added
using the add method with one of the names "North", "South", "East", "West",
or "Center". These named components are arranged along the edges and in
the center of the container. The two arguments used in the constructor
of the BorderLayout class represent the desired horizontal and vertical
spacing between adjacent components.
Let's look at a simple example
import java.awt.*;
import java.applet.*;
public class testBL extends Applet{
Button nb1,nb2,sb,eb,wb,cb;
Panel pan;
public void init() {
nb1 = new Button("This is North");
nb2 = new Button("This is also North");
sb = new Button("This is South");
eb = new Button("This is East");
wb = new Button("This is West");
cb = new Button("This is Center");
pan = new Panel();
pan.setLayout(new BorderLayout(0,0));
pan.add("East",nb2);
pan.add("West",nb1);
this.setLayout(new BorderLayout());
this.add("North",pan);
this.add("South",sb);
this.add("East",eb);
this.add("West",wb);
this.add("Center",cb);
}
}
This code will generate an applet that
has all the buttons set on sides or right in the middle. Note that you
can use the Panel class to group together buttons before you glue
them to the sides or to the middle. The Panel can have it's own
layout setup, and it does not have to be the same as the main layout setup.
CardLayout
This is a LayoutManager that ensures that only one of the components it
manages is visible at one time. The standard LayoutManager methods are
called by the container and should not be called directly by the applet.
FlowLayout
This class implements the Layout Manager interface to lay out component
objects in a container. FlowLayout arranges components from left
to right in rows. It fits as many components as possible in a row before
moving on to the next row. The constructor allows you to specify the one
of three constants as an alignment value for the rows, and also allows
you to specify horizontal and vertical spacing between components.
import java.awt.*;
import java.applet.*;
public class testFL extends Applet{
Button nb,pb,b1,b2,b3;
Panel pan,pan2;
public void init() {
nb = new Button("Next ");
pb = new Button("Previous ");
b1 = new Button("Button1");
b2 = new Button("Button 2");
b3 = new Button("Button 3");
pan = new Panel();
pan.setLayout(new FlowLayout(FlowLayout.CENTER,40,10));
pan.add(nb);
pan.add(pb);
pan2 = new Panel();
pan2.setLayout(new FlowLayout(FlowLayout.CENTER,40,10));
pan2.add(b1);
pan2.add(b2);
pan2.add(b3);
this.setLayout(new BorderLayout(15,15));
this.add("South",pan);
this.add("North",pan2);
}
}
This code will generate an applet that
has the buttons centered on the top and bottom sides.
GridBagConstraints and GridBagLayout
The GridBagLayout class implements the LayoutManager interface to
lay out components object in a container. It is the most complex, most
powerful and most complicated LayoutManager in the java.awt package.
It divides the container into a grid of rows and columns (which need not
have the same size) and places the components into this grid. Each component
controls how it is positioned within this grid by specifying a number of
variables in a Grid BagConstraints object.
GridLayout
This class implements the LayoutManager interface. It divides the container
into a specified number of rows and columns and arranges the components
in those rows and columns, left-to-right and top-to-bottom. If either the
number of rows or the number of columns is unspecified, it is computed
from the other dimension and the total number of components.
PackerLayout
The PackerLayout
was developed by Daeron Meyer from
the Geometry Center, UMN, in October
95. This class implements the LayoutManager interface and allows the user
to set the properties at a component level instead at a container level.
In order to use this class you have to download
the source code, compile it, and set it in the same directory with your
applet that uses it. There are no arguments passed to the constructor of
the PackerLayout class. Instead, the add method reads everything
from within a string.
To initialize it, we use the same method, setLayout, as in the
previous examples. When we add the components, using the add method, we
have to call it using a string built from options. These options
are explained in the following table.
Name |
Explanation |
Possible values |
(name) |
a name for this component; can be the same with the variable name;
the name should be unique |
any string name |
side |
the side to which the components should be added |
left, right, top, bottom |
fill |
expands the size of the component to take the maximum possible size
inside the container |
x,y,both |
anchor |
the direction in which the component should go inside the container
until there is no more empty space |
s,n,e,w,se,sw,ne,nw |
expand |
resize the component if the window is resized |
true,false |
padx,pady |
space around the component on horizontal (x) or vertical (y) direction
that should be left empty |
integer (represents pixels) |
ipadx,ipady |
defines how much we want to expand the size of the component in each
direction (for Button for example this is the space to be left between
the name of the button and the edge of the button) |
integer (represents pixels) |
Note that there should be no space inside this string. All the options
are separated by ";". For example, a valid string will be
"button1;side=left;fill=x;ipadx=5;ipady=2;padx=3;pady=3;anchor=sw",
while
"button1; side=left;fill=x;ipady=2;ipadx=5;padx=3;pady=3;anchor=sw"
will generate an error since there is a space character inside the
string.
Let's look at some simple examples,
wrote by the creator of PackerLayout.
A more complex example was constructed using the applet
from the previous class. In the code
of this applet we used the generic default LayoutManager from the JDK.
Let's try now to rewrite the code
and make the interface look nicer.
Using the Image class
Up to now, each time we wanted to draw something we did it inside the applet,
on the default drawing are. These is an easy way out, but there are some
problems related to this: each time we have to redraw the are, we either
use the drawing or we have to redraw everithing again (if we kept the information
somewhere in the memory). There is a nice way to avoid this problem. There
exists inside the java class structure a component called Image.
This class generates an image in which the user can draw using the same
Graphics class methods. Then, we can draw this image on the default
applet graphic are using the drawImage() Graphics method.
A particular aspect of the Image class is that ther is no direct
constructor. To create it we have to use the createImage() method
from within the applet. After the image was created, all we have to do
is to obtain a "pointer" to its Graphics class using the getGraphics()
method.
In this example, I extended
the code from the previous example to a Scribble that never looses
the drawing.