Week 11 - March 30, 1999

Designing the GUI layout
Using the Image class

 

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.