Copyright Chris Johnson, 1998.
This course must NOT be used for any commercial purposes without the express per mission of the author.

Human Computer Interface Design Using Java

Chris
USING THE ABSTRACT WINDOW TOOLKIT (Part 4)
by

Chris Johnson



Layout Managers

When we discussed the component hierarchy, we described the Container class as including higher level objects such as Dialog Boxes and Windows. It provides a means of "grouping" multiple components. For instance, an applet may contain a number of buttons. Layout managers, in contrast, controls the size and position of components in a container. Every Container has a LayoutManager object by default. As we shall see, the default layout manager for a window is a BorderLayout object. It is, however, relatively simple to change this default should you need to:

All of this is important because LayoutManagers must respond each time a user moves or resizes a container. The section on text showed how different fonts may lead to some warning being displayed outside the limits of their frame. This is a general problem if users resize dialogue boxes so that they can no longer present all of their components. As a result, user interface design can be substantially improved if programmers and designers spend some time selecting an appropriate LayoutManager.

AWT provides a number of methods for the LayoutManager class that help to address some of the problems mentioned above. For example, programmers can indicate the preferredLayoutSize and minimumLayoutSize for a container. This helps to avoid the problem of re-sizing a dialogue box or window below the minimum value.

Some LayoutManagers allow their programmers to specify constraints on the objects within a container. For instance, BorderLayout enables inerface designers to specify that components should be placed within the Border at North, South, East, West and Center positions. In contrast, the FlowLayout simply places components from left to right and from top to bottom within the container.

BorderLayout
As mentioned, a BorderLayout has five areas: North; South; East; West and Center. These are illustrated by the following application. If you are feeling comfortable with the material covered up to this point then the code for this button applet is available
here. More importantly for this section, the listing for the BorderLayout application is here. This is written in AWT1.0 as given in the Sun tutorials. A 1.1 example follows.

Try to resize the window that appears after selecting the button. You should see that the central component expands to fill the available space. As a result, this layout manager is particularly useful for applications that require a central working area and a number of peripheral components, such as toolbars or buttons.

The following code provides a simpler example of the BorderLayout without resorting to AWT1.0 code. It consists of two files - the first creates a closeable frame class that is based on the code that has been used in previous examples.

/*
* Class to create a closeable frame
*
* Author: Chris Johnson (johnson@dcs.gla.ac.uk)
* Last revision date: 5/1/2000
*
*/
 
import java.awt.*;
import java.awt.event.*;
 
public class CloseableFrame extends Frame
{
 
static private final int frame_height = 150;
static private final int frame_width = 250;
 
       public CloseableFrame()
        {
 
         addWindowListener(new
          WindowAdapter()
          {
            public void windowClosing(WindowEvent e)
             {System.exit(0);}
          }
         );
 
          setTitle("A Frame");
          setSize(frame_width, frame_height);
        }
}
The second of the two files then extends the previous class to create a closable frame that contains some buttons. These are then added to the frame using a BorderLayout.
import java.awt.*;
import java.awt.event.*;
 
public class ButtonTest extends CloseableFrame
	{
		public ButtonTest()
		{
			setLayout(new BorderLayout());
			add("North", new Button("North Label"));
			add("South", new Button("South Label"));
			add("East", new Button("East Label"));
			add("West", new Button("West Label"));
			add("Center", new Button("Center Label"));
		}
 
	public static void main(String [] args)
	{
		ButtonTest f = new ButtonTest();
		f.show();
	}
}

CardLayout
This manages two or more components that share the same display space. These components can be thought of as a deck of cards. Programs can select the card to be shown on the top by:

The CardLayout.show() method can be used to set the currently showing component. The first argument is the container that the CardLayout controls. The second argument is the string that identifies the component, see above.

The following application illustrates the use of the CardLayout manager, again using a button to access the Java application. The listing for the CardLayout application is here.


Your browser can't run 1.0 Java applets.

FlowLayout

This manager places its components in a row. The size of these components is based upon their preferred size. If the width of the container is too small then the FlowLayout LayoutManager will use multiple rows. By default, each row is centred but programmers can choose left or right justification if necessary. It is also possible to use a three parameter version of the constructor method to specify a certain number of pixels as a gap between components: public FlowLayout(int alignment, int horizontalGap, int verticalGap). The default value is 5 pixels in both dimensions.

The following application illustrates the use of the FlowLayout manager, again using a button to access the Java application. The listing for this FlowLayout application is here.


Your browser can't run 1.0 Java applets.

GridLayout

Programmers can use a GridLayout to displays components in a requested number of columns and rows. Each of these components is constrained to have an equal size. If you resize a GridLayout then each of the component cells is resized to be as large as possible within its container. The following code is used in the example, see below:

//Construct a GridLayout with 2 columns and an unspecified number of rows.
            setLayout(new GridLayout(0,2));
            setFont(new Font("Helvetica", Font.PLAIN, 14));
               
            add(new Button("Button 1"));
            add(new Button("2"));
            add(new Button("Button 3"));
            add(new Button("Long-Named Button 4"));
            add(new Button("Button 5"));

The constructor tells the GridLayout class to create an instance that has two columns. The 0 paramter allows the manager to create as many rows as necessary. However, at least one of the row/column arguments must be non-zero.

The following application illustrates the use of the GridLayout manager, again using a button to access the Java application. The listing for this GridLayout application is here.


Your browser can't run 1.0 Java applets.

GridBagLayout

As the name suggests, GridBagLayout places components within a grid. The rows in the grid can be of different heights, the columns can have different widths. This manager uses the components' preferred sizes to determine how big the cells in the grid should be. Components can also span more than one cell.

Programmers can use a system of weights to specify the resizing behavior of a GridBagLayout. The greater the weight associated with a component then the more space is allocated to it when it becomes available. For example, the following program assigns any increased vertical space to the last row of the applet. However, any additional horizontal space is split evenly among all of the columns.

The following application illustrates the use of the GridBagLayout manager, again using a button to access the Java application. The listing for this GridLayout application is here.


Your browser can't run 1.0 Java applets.

This applet uses constraints to specify the size and position of its components. Instance variables are set in a GridBagConstraints object. GridBagLayout (with the setConstraints() method) then associates the constraints with the component. These constraints include:

More details and examples of this class are available. The following case study provides a practical example of the application of constraints to a GridBagLayout.


The Calculator Case Study

This Applet is based on a program developed by G.W. Rowe in An Introduction to Data Structures and Algorithms with Java, Prentice Hall, 1998, pp50-81.

This program implements a simple four function calculator. In order to build its user interface, we need to layout the numeric keys and the function keys in the positions that one might expect for a pocket calculator. This can be achieved through the GridBagLayout Manager mentioned above. Recall that GridBagLayout enables programmers to place components anywhere within the grid rather than being forced to follow the left to right and top to bottom ordering of GridLayout. In particular, constraints can be used to set the position, size etc of components within the columns and rows of a grid.

The Applet relies upon the following classes:

Here is the final Applet.

Extensions:

A simple way of "polishing" the interface to this applet would be to center the results panel in relation to the keypads. It might also be increased in width. Hint: look at the section on constraints in the previous paragraphs.

The functions supported by the calculator might also be extended to include trigonometic functions.

Notice how the text area that presents the results fills from the left. This text field reflects the usual practice in Western scripts. However, most calculators present their numbers in a right justified format. Can you think of any simple way of addressing this problem to provide a more familliar user interface to the calculator?


The previous discussion on the application of Layout Managers can be summarised by the following table:

Layout Manager Description Example
BorderLayout Components divided into regions
north, south, east and west.
Central work area with peripheral button
CardLayout Controls visibility of a number of
components - can move an item
to the top or bottom of a pile.
A stack of tabbed folders.
A spiral bound note-pad.
FlowLayout Fills container from left to right
and from top to bottom.
Simple layouts with similar sized components.
GridLayout Programmers place components
within a grid, all cells are the
same size.
A Calendar
GridBagLayout Complicated and flexible placement of components
in a grid
Most form based user interfaces.


Windows, Frames and Dialogs

AWT provides three classes for displaying a window on the screen. A portion of its class hierarchy illustrates the relationship between Windows, Dialogs and Frames.

                                     Object
                                        |
                                    Component
                                        |
			     ------------
		       Container  
                          |
                     -----------  
                  Panel       Window 
                                |
                            ----------
                        Dialog       Frame
                          |
                     FileDialog
Windows are the most basic of the three forms. They have no border, titlebar or menubar and they cannot be resized. This means that for most purposes they are too inflexible as basic interface constructors. However, the following case study makes use of this component sub-class.

The balloon help/tooltips case study.
This is based on an Applet developed by D.M. Geary in Graphic Java 1.1, Sunsoft Press, 1997, p.244. His version is based on AWT1.1 - I've adapted it to run under AWT1.0.

Many user interfaces provide people with hints about the commands that they support. For example, MacOS allows users to turn on Ballon help. This displays information about menu items, buttons etc as the user's mouse moves over them. These balloons can be though of a primitive windows. They take up an area of the screen but they do not need a title bar nor are they scrollable. They simply present a textual explanation to the user.

The following list describes the components that can be used to implement this interface technique. However, this Applet has not been compiled. To understand the reasons why, read the comment in this file. This application requires the following:

Bubble.java calls the pack() method defined by the Window class. This resizes the window so that its contents are at or above their preferred or minimum sizes. This is better than calling resize() because pack() uses the window's layout manager to adjust for platform dependencies and other factors that affect component size.

An interesting aspect to this example is that it will run successfully on some Java virtual machines and not on others. For instance, the Macintosh SemanticCafe AppletViewer will run this - events are passed from the simple Bubble windows to the handleEvent() method in BubbleTest.java. In other environments, these events are not passed up the hierarchy. As a simple exercise, you should, therefore, write a handleEvent() method inside Bubble.java. Take a look at the code for the simple dialog example, discussed below, for an illustration of how this can be done.


Frames extend windows to include a border and a titlebar. They are also resizable. It is also possible to associate menubars with frames. The Frame class provides windows for applets and applications. We have already met several examples of this component because every application requires at least one frame. This example was introduced previously:

/*
* A frame 
*
* Author: Chris Johnson (johnson@dcs.gla.ac.uk)
* Last revision date: 11/10/98
*
* Produces a warning window on the screen
* AWT version 1.0.
*
* Beware - there is no way of closing the frame!
* see later section on event handling...
*/
 
import java.awt.*;
 
public class SimpleWarningFrame extends Frame {
 
static private final int frame_height = 150;
static private final int frame_width = 250;
 
public SimpleWarningFrame () {
        setBackground(Color.red);
        setForeground(Color.black);
}
 
   public static void main (String[] args){
 
        Frame f= new SimpleWarning();
        f.setTitle("Warning");
        f.resize(frame_width, frame_height);
        f.show(true);
   }
}

There are, however, circumstances where Dialogs are more appropriate than Frames. This occurs when one window is dependent upon another. For example, if a user selects a command to find a file or folder they are often presented with a widow that contains a "further options" button. If they select this option then they are presented with another window that is dependent upon the first. In other words, the further options depends upon the original search window because it cannot be reached without first going through this initial find window. Also, if the find window is dismissed then the further options window is also dismissed. Many user interfaces exploit modal dialogues. These prevent users from interacting with other aspects of the system until they have confirmed or dismissed that dialogue. However, the AWT default is that dialogs are non-modal. Users can keep up a dialog and can continue to work in other application widows.

The following Applet illustrates the use of a Dialog Window. The code for this program is here. It forms the example for the exercise of DEBUGGING and if you havent read this exercise before now then please take some time to look at it before moing on. Beware, this applet does run successfully under MacOS and NT but it will not run successfully on Solaris. A selection event is received on the initial dialogue button when this page is first launched. Similar problems affect the more complex applet, given below, and developed by Sun themselves.

Here is a more complex example using a button to access the application. Here is the code.


Your browser doesn't understand the <APPLET> tag.

The AWT Dialog class provides relatively few facilties compared to other interface development tools. It does, however, provide one extremely useful subclass; FileDialog. Here is the code for an Applet that illustrates this component. Why is it a good thing that this wont run from within a web browser? (Hint: think of the security implications of allowing an applet to write to your local disk space?)

By default, a file dialog is created to load a file. Hence the example explicitly requests a save dialog when the appropriate button is pressed:

dialog = new FileDialog(myFrame, "Save A File", FileDialog.SAVE);
The actual dialog that the user is presented with will vary from platform to platform. For example, Windows95 will ask the user to confirm if they are about to overwrite a file while Solaris does not. Of couse, you as the programmer then has to call the various methods that will actually write the data to the file chosen by the user or will read the data from that file into the corresponding objects within the application program.

And now on to part five...


Copyright Chris Johnson, 1998.