Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

The AWT Package, The Container, Panel, Window, and Frame Classes

Java Programming, Lecture Notes # 130, Revised 01/05/98.

Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson.

This lesson, and the next several lessons will concentrate on the use of the GUI components available in the JDK 1.1.x release. You should also be aware that an entirely new set of lightweight GUI components, known collectively as the Swing set, are in the pre-beta evaluation stage at JavaSoft as of January 1998.

It is rumored that JDK 1.2 (or perhaps 2.0) will be released in the first or second quarter of 1998, and that the Swing components will be part of that release.

The Swing components are not intended to replace the AWT components from JDK 1.1, but rather are intended to supplement those components with a set of components that provide a consistent look and feel across all platforms. In addition to providing a consistent look and feel, several components (such as progress bars) are included in the Swing set that are not included in the JDK 1.1 AWT.

Introduction

This series of lessons is concentrating on package java.awt where most of the functionality exists for providing the user interface to your application or applet.

We have learned how to handle events in both JDK 1.0.2 and JDK 1.1. We have learned how to use the layout managers in JDK 1.1. These two topics form the basis for the design and implementation of a Graphical User Interface.

The next step is to take a look at the variety of components that are available to combine with layout and event handling to produce an effective Graphical User Interface.

The available components are defined by classes in the package java.awt. Our approach will be to group those classes into categories and study the material on a category basis. As of this writing, it looks as if the categories will be:

However, as things develop, I may find it necessary to modify these groupings.

This lesson will concentrate on the Container classes.

Arranging Components in Containers

We have learned that we can place our components in their containers using absolute position coordinates, or we can use any of several different layout managers to do the job. Using layout managers is considered by many to be the safer approach because this approach tends to automatically compensate for differences in screen resolution and component appearance between platforms.

In our previous studies of layout managers, we made extensive use of Container classes. However, since our emphasis was on layout, we simply took the containers for granted and didn't provide much in the way of discussion relative to the containers themselves.

We will rectify that situation in this lesson and learn more about the Container classes.

The Container Classes

The following hierarchy diagram shows where the Container classes Panel, Window, and Frame fit into the overall inheritance hierarchy. We will discuss these three classes as a group, and also discuss their relationship with their superclasses Container, Component, and Object.
java.lang.Object 
   | 
   +----java.awt.Component 
           | 
           +----java.awt.Container
                   |
                   +----java.awt.Panel 
                   | 
                   +----java.awt.Window 
                           | 
                           +----java.awt.Frame
Generally, the Container classes are used to contain components or instances of other classes.

The Container Class

As indicated in the hierarchy diagram above, the Container class extends the Component class, which in turn extends the Object class. We will discuss these three starting with the Object class and working our way down to the Container class.

The Object Class

We have discussed the Object class and the Component class in previous lessons. The Object class is a member of the java.lang package, and is the root of the class hierarchy. Every class has Object as a superclass.

All objects, including arrays, implement the methods of the Object class. In keeping with the general concepts of inheritance in Object-Oriented Programming, the methods provided by the Object class are general-purpose in nature.

As of 3/9/97, there are no fields and there are eleven methods in the Object class, including such general-purpose methods as the familiar toString() and finalize() methods.

The Component Class

The Component class extends the Object class, and is the superclass of many of the classes used to produce Graphical User Interfaces.

Component has no public constructors so it cannot be instantiated. However, it can be extended which provides a new capability of JDK 1.1 known as Lightweight Components which will be the topic of a subsequent lesson.

As of 3/9/97, Component has six fields which are inherited by its subclasses. Also as of 3/9/97, Component has more than 100 methods. Thus, many of the methods used by the different classes used to produce GUIs are inherited from the Component class.

The Container Class

The Container class extends Component. As with Component, there are no public constructors for the class. Therefore, you cannot instantiate objects of the Container class. However, you can extend the class giving rise to Lightweight Components as mentioned earlier.

As we will see, the Panel class, the Window class, and the Frame class are subclasses of Container and inherit the methods defined in Container.

During our studies of layout managers, we saw sample programs which used the add() method of the Container class to place other components into objects subclassed from Container.

According to the JDK 1.1 documentation:
"Components added to a container are tracked in a list. The order of the list will define the components' front-to-back stacking order within the container. If no index is specified when adding a component to a container, it will be added to the end of the list (and hence to the bottom of the stacking order)."
As of 3/9/97, Container has no fields and more than forty methods. However, many of these are deprecated methods held over from JDK 1.0, and might be expected to disappear from some future version of the JDK.

The list of methods includes five overloaded versions of the add() method. During our studies of the layout managers, we learned that the different layout managers require the use of different versions of the add() method for placing components into container objects.

The Container class is also the home of the setLayout() method which is used to specify the layout manager for a particular container and the validate() method which is used to cause changes to a layout to take effect. We have used these two methods in numerous sample programs in previous lessons.

The Panel Class

The Panel class inherits from the Container class and can be used to produce a completely generic container. As of 3/9/97, it has no fields and two public constructors. The constructors are: The default layout manager for a Panel object is FlowLayout. It is also possible to specify a different layout manger for the object when it is instantiated, and it is possible to accept the default initially and change it later using the setLayout() method.

As of 3/9/97, Panel has only one method: addNotify(), which is used to creates the Panel's peer. Briefly, the peer is the platform-dependent manifestation of the platform-independent object.

Normally a panel has no visual manifestation in its own right.. However, it is possible to make a panel visible by setting its background color to something other than the default. The following sample program causes three Panel objects to have background colors of yellow, red, and blue in order to make them visible for purposes of illustration.

Sample Program for Panels

This sample program is designed to be compiled and run under JDK 1.1

This program illustrates the use of Panel objects to create a composite top-level Graphical User Interface object. Three Panel objects are added to a Frame object using the add() method.

The layout manager for the Frame object is specified to be FlowLayout using the setLayout() method.

The background colors of the three panels are set to yellow, red, and blue so that they will be visible in the Frame object.

One component is placed on each of the Panel objects using the add() method.

None of these components are active, meaning that event Listener objects are not instantiated and registered for the components. For example, clicking the button does not result in the processing of an event and nothing happens other than the default visual effect of pressing a button.

If you compile and run this program (and make certain that the Frame is sufficiently wide) you should see three Panel objects lined up across the top of the Frame object. The color of the panels going from left to right should be yellow, red, and blue. The yellow panel should contain a TextField object, the red panel should contain a Label object, and the blue panel should contain a Button object.

If the Frame object is not sufficiently wide to accommodate the three panels across the top, they will automatically rearrange themselves in the standard fashion for a FlowLayout manager.

A windowClosing() event listener object is instantiated and registered on the frame to terminate the program when the frame is closed.

The program was tested using JDK 1.1 running under Win95.

Interesting Code Fragments for Sample Panel Program

The following code fragment is typical of that used to instantiate each of the three Panel objects, set the background color of the Panel objects, and add another component to the Panel object.
    Panel leftPanel = new Panel();
    leftPanel.setBackground(Color.yellow);
    leftPanel.add(new TextField("Left Panel is Yellow"));
The following code fragment instantiates a Frame object and adds the three panels constructed above to that object.
Frame myFrame = new Frame("Copyright 1997, R.G.Baldwin");
myFrame.setLayout(new FlowLayout());

myFrame.add(leftPanel);
myFrame.add(middlePanel);
myFrame.add(rightPanel); 
This code produces the top-level user-interface object for the application.

Program Listing for Sample Panel Program

A complete listing of the program follows. See an operational description of the program in an earlier section.
/*File Container01.java Copyright 1997, R.G.Baldwin
This program is designed to be compiled and run under 
JDK 1.1

This program illustrates the use of Panel objects to 
create a composite top-level Graphical User Interface 
object.

The program was tested using JDK 1.1.3 running under Win95.
**********************************************************/

import java.awt.*;
import java.awt.event.*;
//=======================================================//
public class Container01 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class Container01
//=======================================================//

class GUI {
  public GUI(){//constructor
  
    //Build three Panels with colored backgrounds each
    // containing a non-active component.
    
    Panel leftPanel = new Panel();
    leftPanel.setBackground(Color.yellow);
    leftPanel.add(new TextField("Left Panel is Yellow"));
    
    Panel middlePanel = new Panel();
    middlePanel.setBackground(Color.red);
    middlePanel.add(new Label("Middle Panel is Red"));
    
    Panel rightPanel = new Panel();
    rightPanel.setBackground(Color.blue);
    rightPanel.add(new Button("Right Panel is Blue"));

    //Instantiate a Frame object using a FlowLayout manager
    // and place the three Panel objects on the Frame

    Frame myFrame = new Frame(
                            "Copyright 1997, R.G.Baldwin");
    myFrame.setLayout(new FlowLayout());

    myFrame.add(leftPanel);
    myFrame.add(middlePanel);
    myFrame.add(rightPanel);    
    myFrame.setSize(500,200);
    myFrame.setVisible(true);
    
    
    //Instantiate and register a window listener to 
    // terminate the program when the Frame is closed.
    
    myFrame.addWindowListener(new Terminate());
  }//end constructor
}//end class GUI definition
//=======================================================//

class Terminate extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);//terminate the program
  }//end windowClosing
}//end class Terminate
Next we will turn our attention to the Window class which also extends the Container class.

The Window Class

As shown in the earlier hierarchy diagram, the Window class extends the Container class. It is a top-level window with no borders and no menubar. The JDK documentation indicates that it could be used, for example, to implement a pop-up menu.

The default layout for a Window object is BorderLayout. Windows are capable of generating the following window events:

As of 3/9/97, the Window class has no fields, one public constructor, and about fifteen methods. Some of the methods are deprecated methods left over from JDK 1.0.

The definition of the constructor is as follows:
public Window(Frame parent) 
  • Constructs a new Window initialized to an invisible state. It behaves as a modal dialog in that it will block input to other windows when shown. 
  • Parameters: parent - the owner of the dialog 

Now, having given you that information, let me tell you that of the approximately twenty books on Java programming that I currently own, all but about three are silent on the topic of the Window class. Let me share with you what those books that are not silent have to say on the matter.
"Window is rarely used directly; its subclasses Frame and Dialog are more commonly useful." -- Java in a Nutshell, by David Flanagan.
.
"Generally you won't create Window objects directly. Instead, you will use a subclass of Window called Frame, described next." -- Java, the Complete Reference, by Herbert Schildt and Patrick Naughton.
.
"The Window class is a lot like Panel except that it creates its own top-level window, as opposed to being contained by any other Panel. Most users of the Window class will more than likely use the Frame subclass, described below, which has several convenience methods to deal with resizing, window titles, cursors, and menu bars. That said, let's skip ahead to the Frame class." -- The Java Handbook, by Patrick Naughton.
With all that good advice, let's take Mr. Naughton's advice specifically, and skip ahead to the Frame class which is our next topic of discussion.

The Frame Class

Unless you just started reading these lessons at this paragraph, you will not be a stranger to the use of the Frame class. That is the class that I have primarily been using for most of my sample programs for about the past ten to fifteen lessons.

I particularly like to use the Frame class for sample programs because it is easy to instantiate, and equally important, it is easy to terminate.

The Frame class extends the Window class. A Frame object is an (optionally) resizable top-level window with

The default layout for a Frame object is BorderLayout.

Frames are capable of generating the following types of window events:

The WindowClosing event, highlighted in the earlier program, is the event that we have used to terminate many sample programs. This event occurs whenever the user clicks the close box on the Frame object.

As of 3/9/97, the Frame class had fourteen fields, all of which are used in dealing with the appearance of the cursor.

Also, as of that date, it had two overloaded public constructors:

You will recall that all of our sample programs have used the setVisible(true) method to cause the initially invisible Frame object become visible.

In addition, on 3/9/97, the Frame class had more than a dozen methods, a couple of which were deprecated methods left over from JDK 1.0.2. Some of the deprecated methods have to do with getting and setting the cursor. From the specifications, it appears that those methods have been moved up the hierarchy to the Component class.

Sample Program for Frame Class

This program is designed to be compiled and run under JDK 1.1

This program illustrates use of the Frame class and some of its methods. The program instantiates a Frame object with three buttons labeled:

When the user clicks the Get Title button, the title of the Frame object is retrieved using the getTitle() method of the Frame class and displayed on the screen using a System.out.println statement.

When the user clicks the Hand Cursor button, the shape of the cursor is changed to the familiar hand-shaped cursor using the setCursor() method.

When the user clicks the Default Cursor, the shape of the cursor is changed back to the default cursor for the system.

Note that in the two latter cases, you must move the mouse pointer away from the button to see the change in the cursor take place.

This is an extremely simple program in comparison with other programs already studied in these lessons.

To prevent the program from being boring, I decided to use this opportunity to review the abbreviated syntax of Inner Classes (a topic covered in an earlier lesson).

All of the event Listener objects are instantiated and registered on the three Button objects and the "close" box using the abbreviated syntax of Inner Classes. If this looks foreign to you, you might want to go back and review that lesson.

A windowClosing() event listener object is instantiated and registered on the frame to terminate the program when the frame is closed.

The program was tested using JDK 1.1 running under Win95.

Interesting Code Fragments from Sample Program for Frame Class

The following statement is typical of those used to instantiate the Button objects in the program.
Button titleButton = new Button("GetTitle");
The following code is typical of that used to .
myFrame = new Frame("Copyright 1997, R.G.Baldwin");
myFrame.setLayout(new FlowLayout());

myFrame.add(titleButton);
The following code fragment is typical of that used to instantiate and register ActionListener objects on the three Button objects using the abbreviated syntax for Inner Classes.
titleButton.addActionListener(
             new ActionListener(){
               public void actionPerformed(ActionEvent e){
                 System.out.println(myFrame.getTitle());
               }//end actionPerformed()
             }//end ActionListener 
           );//end addActionListener()
The following code was used to instantiate and register a WindowListener object on the Frame object to terminate the program when the user clicks the "close" box on the Frame object.
myFrame.addWindowListener(
                new WindowAdapter(){
                  public void windowClosing(WindowEvent e){
                    System.exit(0);//terminate the program
                  }//end windowClosing()
                }//end WindowAdapter
              );//end addWindowListener
.

Program Listing for Sample Program for Frame Class

A complete listing of the program follows:
/*File Container02.java Copyright 1997, R.G.Baldwin
This program is designed to be compiled and run under 
JDK 1.1

This program illustrates use of the Frame class and some
of its methods.


The program was tested using JDK 1.1.3 running under Win95.
**********************************************************/

import java.awt.*;
import java.awt.event.*;
import java.util.*;
//=======================================================//
public class Container02 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class Container02
//=======================================================//

class GUI {
  Frame myFrame;
  public GUI(){//constructor

    //Instantiate three Button objects with the 
    // labels shown
    Button titleButton = new Button("GetTitle");
    Button handCursorButton = new Button("Hand Cursor");
    Button defaultCursorButton = new Button(
                                         "Default Cursor");
    
    //Instantiate a Frame object with title shown. 
    // Specify FlowLayout mgr.
    myFrame = new Frame("Copyright 1997, R.G.Baldwin");
    myFrame.setLayout(new FlowLayout());
    
    //Add the three Button objects to the Frame object.
    myFrame.add(titleButton);
    myFrame.add(handCursorButton);
    myFrame.add(defaultCursorButton);
    
    //Set the Frame size and make it visible
    myFrame.setSize(250,200);
    myFrame.setVisible(true);    

    //Instantiate and register ActionListener objects on
    // the three Button objects using the abbreviated 
    // syntax for Inner Classes.  
    //---------------------------------------------------//
    
    titleButton.addActionListener(
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
               System.out.println(myFrame.getTitle());
             }//end actionPerformed()
           }//end ActionListener
         );//end addActionListener()
    //---------------------------------------------------//
    
    handCursorButton.addActionListener(
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
               myFrame.setCursor(
                           new Cursor(Cursor.HAND_CURSOR));
             }//end actionPerformed()
           }//end ActionListener
         );//end addActionListener()
    //---------------------------------------------------//
    
    defaultCursorButton.addActionListener(
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
               myFrame.setCursor(
                        new Cursor(Cursor.DEFAULT_CURSOR));
             }//end actionPerformed()
           }//end ActionListener
         );//end addActionListener()
    //---------------------------------------------------//

    //Instantiate and register a WindowListener object 
    // on the Frame object to terminate the program when
    // the user clicks the "close" box on the Frame object.
    myFrame.addWindowListener(
           new WindowAdapter(){
             public void windowClosing(WindowEvent e){
               System.exit(0);//terminate the program
             }//end windowClosing()
           }//end WindowAdapter
         );//end addWindowListener

  }//end constructor
}//end class GUI definition
.

Review

Q - Write a Java program that meets the following specifications.
/*File SampProg146.java Copyright 1997, R.G.Baldwin
From lesson 130.

Without viewing the solution that follows, write a Java
program that meets the following specifications.

When the program starts, a 500x100 Frame object appears
on the screen with your name in the top banner.

The Frame contains a yellow rectangle that fills most of
the white client area of the Frame.

The yellow rectangle contains two objects which are not
necessarily the same size.  On the left is a TextField 
containing the text "Left Panel is Yellow". On the 
right is a red rectangle.

The red rectangle contains two objects which are 
approximately the same size.  On the left is a green
rectangle containing the text "Middle Panel is Red".
On the right is a blue rectangle.

The blue rectangle contains a button with the caption
"Right Panel is Blue".

When you click the close button on the Frame, the program
terminates and returns control to the operating system.

The program was tested using JDK 1.1.3 running under Win95.
**********************************************************/

import java.awt.*;
import java.awt.event.*;
//=======================================================//
public class SampProg146 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class SampProg146
//=======================================================//

class GUI {
  public GUI(){//constructor
  
    //Build three Panels with colored backgrounds each
    // containing a non-active component.
    
    Panel leftPanel = new Panel();
    leftPanel.setBackground(Color.yellow);
    leftPanel.add(new TextField("Left Panel is Yellow"));
    
    Panel middlePanel = new Panel();
    middlePanel.setBackground(Color.red);
    Label myLabel = new Label("Middle Panel is Red");
    myLabel.setBackground(Color.green);
    middlePanel.add(myLabel);
    
    Panel rightPanel = new Panel();
    rightPanel.setBackground(Color.blue);
    rightPanel.add(new Button("Right Panel is Blue"));

    //Instantiate a Frame object using a FlowLayout 
    // manager and place the three Panel objects on the 
    // Frame in a nested fashion

    Frame myFrame = new Frame(
                            "Copyright 1997, R.G.Baldwin");
    myFrame.setLayout(new FlowLayout());
    
    middlePanel.add(rightPanel);
    leftPanel.add(middlePanel);
    myFrame.add(leftPanel);
    myFrame.setSize(500,100);
    myFrame.setVisible(true);
        
    //Instantiate and register a window listener to 
    // terminate the program when the Frame is closed.
    
    myFrame.addWindowListener(new Terminate());
  }//end constructor
}//end class GUI definition
//=======================================================//

class Terminate extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);//terminate the program
  }//end windowClosing
}//end class Terminate
//=======================================================//
.

Q - Write a Java program that meets the following specifications.
/*File SampProg147.java Copyright 1997, R.G.Baldwin
From lesson 130

Without viewing the following solution, write a Java
program that replicates the functionality of the program
named Container02.java with the following differences.

1.  Use a crosshair cursor in place of a hand cursor
2.  Don't use an abbreviated inner-class for the action
    listener on the getTitle button.  Use an ordinary
    inner-class instead.


The program was tested using JDK 1.1.3 running under Win95.
**********************************************************/

import java.awt.*;
import java.awt.event.*;
import java.util.*;
//=======================================================//
public class SampProg147 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class SampProg147
//=======================================================//

class GUI {
  Frame myFrame;
  public GUI(){//constructor

    //Instantiate three Button objects with the 
    // labels shown
    Button titleButton = new Button("GetTitle");
    Button crosshairCursorButton = 
                            new Button("Crosshair Cursor");
    Button defaultCursorButton = new Button(
                                         "Default Cursor");
    
    //Instantiate a Frame object with title shown. 
    // Specify FlowLayout mgr.
    myFrame = new Frame("Copyright 1997, R.G.Baldwin");
    myFrame.setLayout(new FlowLayout());
    
    //Add the three Button objects to the Frame object.
    myFrame.add(titleButton);
    myFrame.add(crosshairCursorButton);
    myFrame.add(defaultCursorButton);
    
    //Set the Frame size and make it visible
    myFrame.setSize(250,200);
    myFrame.setVisible(true);    

    //Instantiate and register ActionListener objects on
    // the three Button objects using the abbreviated 
    // syntax for Inner Classes.  
    //---------------------------------------------------//

    class MyActionListener implements ActionListener{
      public void actionPerformed(ActionEvent e){
        System.out.println(myFrame.getTitle());
      }//end actionPerformed()
    }//end class MyActionListener
    titleButton.addActionListener(new MyActionListener());
    //---------------------------------------------------//
    
    crosshairCursorButton.addActionListener(
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
               myFrame.setCursor(
                      new Cursor(Cursor.CROSSHAIR_CURSOR));
             }//end actionPerformed()
           }//end ActionListener
         );//end addActionListener()
    //---------------------------------------------------//
    
    defaultCursorButton.addActionListener(
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
               myFrame.setCursor(
                        new Cursor(Cursor.DEFAULT_CURSOR));
             }//end actionPerformed()
           }//end ActionListener
         );//end addActionListener()
    //---------------------------------------------------//

    //Instantiate and register a WindowListener object 
    // on the Frame object to terminate the program when
    // the user clicks the "close" box on the Frame object.
    myFrame.addWindowListener(
           new WindowAdapter(){
             public void windowClosing(WindowEvent e){
               System.exit(0);//terminate the program
             }//end windowClosing()
           }//end WindowAdapter
         );//end addWindowListener

  }//end constructor
}//end class GUI definition
-end-