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

Swing and the Delegation Event Model

Java Programming, Lesson # 81, Revised 05/09/98.


Preface

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

Introduction

To begin with, what is Swing?

Swing is the name given to a new set of lightweight components developed by JavaSoft to supplement (and possibly replace) the components in the AWT.  (The general topic of lightweight components is covered in a separate lesson.)  With the exception of top-level containers, Swing components are developed completely using Java and don't depend on the peer component rendering provided by the operating system.

Swing components have several advantages over AWT components, and probably some disadvantages as well.

One of the advantages is that because the components are not rendered on the screen by the operating system, the look and feel of a component does not change as the application or applet is executed on different platforms running under different operating systems.

Furthermore, it is possible to cause Swing components to mimic the look and feel of a specific platform no matter what platform the program is running on.  This is known as pluggable look and feel.  A complete lesson is dedicated to pluggable look and feel.

In any event, Swing components are here to stay, and from this point forward in these tutorial lessons, we will attempt to incorporate Swing into the lessons in a meaningful way.

Swing components support the JDK 1.1 Delegation Event Model.  They do not support the JDK 1.0 event model, so if you want to use Swing components, you must program using the Delegation Event Model.

In some cases, conversion of an application or applet from AWT components to Swing components involves nothing more complex than replacing the AWT components with corresponding Swing components.  For example, the Swing component that corresponds to the AWT Button component is the Swing JButton component.

In all cases that you use Swing you will need to import, or otherwise recognize the package that contains the Swing classes so that the compiler and interpreter will have access to those classes.  Note that the way to do this will probably change between JDK 1.1.x and JDK 1.2, but hopefully the change won't be too great. (Rumor has it that Swing will be more tightly integrated into JDK 1.2 than is the case with JDK 1.1.)

This lesson is designed as a follow-on to the earlier lesson entitled "Event Handling in JDK 1.1, A First Look, Delegation Event Model."  As such, material presented in that lesson will not be repeated here.

The two AWT sample programs in that lesson were converted to Swing programs for presentation in this lesson using the simple substitution procedure described above.  As you will see, the Swing version of one of the sample program behaves essentially the same as its AWT counterpart.  The Swing version of the other sample program does not behave the same as its AWT counterpart.

So, where does that leave us?  Well, fortunately, from an event handling viewpoint, Swing components operate the same as AWT components (except that Swing provides a number of new event types).  From other viewpoints, Swing components may or may not behave the same as their AWT counterparts.

In addition, many Swing components don't have an AWT counterpart.  A number of new and exciting components are included in the Swing library that don't exist in the AWT (tooltips, progress bars, trees, etc.).

Since this lesson is primarily concerned with event handling, we will pursue the Swing components from an event-handling viewpoint in this lesson and leave other considerations surrounding Swing components for subsequent lessons. As you will see, this lesson will raise some interesting questions regarding the behavior of Swing components, but won't provide the answers to those questions.  

Sample Program

The sample program in this section, named SwingEvent08, was created by replacing each instance of Frame in the program named Event08, with an instance of JFrame.  In addition, an import statement was added to cause the Swing classes to be accessible to the compiler and the interpreter.

The event handling in this program is exactly the same as in Event08.  If you haven't reviewed that program, and the lesson on the Delegation Event Model, you should probably go back and review it now.

This program illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model for Swing components.

Briefly, this application instantiates an object which creates a user interface consisting of a simple JFrame object. This object is an Event Source which notifies two different Event Listener objects of Window events.

One of the Listener objects implements the WindowListener interface and defines all of the methods declared in that interface.

The other Listener object extends the Adapter class named WindowAdapter. As explained in the earlier lesson, the purpose of Adapter classes (as used in this context) is to implement the Listener interfaces and to define all of the methods with empty methods. (Adapter classes are viewed in a broader context in the advanced lessons on the Reflection API.)

Classes which extend the Adapter classes can then selectively override only those methods of interest. This Listener object overrides only two of the methods.

Note that this application does not terminate and return control to the operating system. You must forcefully terminate it.

This program was tested using JDK 1.1.6 and Swing 1.0.1 under Win95.

The output produced by running the program is presented in the comments at the beginning of the program listing.

Interesting Code Fragments

The first and only code fragment, that I am going to show and discuss is the beginning of the constructor for the GUI class that illustrates that this program uses the JFrame class to instantiate a top-level container for the graphical user interface.  

class GUI{
  public GUI(){//constructor
    //Create a new JFrame object
    JFrame displayWindow = new JFrame();
    displayWindow.setSize(300,200);
    displayWindow.setTitle("Copyright 1998, R.G.Baldwin");

If you compile and run this program, you will see that it behaves essentially the same as its AWT counterpart named Event08 that was discussed extensively in an earlier lesson.

Program Listing

This section contains a complete listing of the program.

/*File SwingEvent08.java Copyright 1998, R.G.Baldwin
Rev 05/09/98

This is a Swing version of the program named Event08.

The purpose of this program is to illustrate that in many
respects, programming with Swing components is no different
from programming with AWT components.

Conversion of this program from AWT to Swing involved
nothing more complex than using the search and replace
feature of an editor to replace all instances of Frame
with JFrame and to import the swing package.

Illustrates the use of Event Sources, Event Listeners, and
Adapters in the Delegation Event Model for Swing
components.

Briefly, this application instantiates an object which 
creates a user interface consisting of a simple JFrame 
object.  This object is an Event Source which notifies two
different Event Listener objects of Window events.

One of the Listener objects implements the WindowListener
interface and overrides all of the methods declared in 
that interface.

The other Listener object extends the Adapter class named 
WindowAdapter.  The purpose of Adapter classes is to
implement the  Listener interfaces and to define all of
the methods with empty methods.  Classes which extend the
Adapter classes can then selectively override only those
methods of interest.  This Listener object overrides only
two of the methods.

Note that this application does not terminate and return
control to the operating system.  You must forcefully
terminate it.

Tested using JDK 1.1.6 and Swing 1.0.1 under Win95.

When executed, this application places a simple empty 
JFrame object on the screen.  

Starting the program produces screen output similar to
the following:
  
WProc1 windowActivated test msg
Wproc1 windowOpened test msg

Pressing the minimize button on the JFrame produces the 
output similar to the following:

WProc1 windowIconified test msg
******** WProc2 windowIconified test msg
WProc1 windowDeactivated test msg

Restoring the JFrame after minimization produces the 
output similar to the following:

WProc1 windowActivated test msg
WProc1 windowDeiconified test msg
******** WProc2 windowDeiconified test msg
WProc1 windowActivated test msg

Closing the JFrame by pressing the X-icon in the upper 
right of the JFrame produces output similar to the 
following:

WProc1 windowClosing test msg
WProc1 windowDeactivated test msg
WProc1 windowClosed test msg
**********************************************************/

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class SwingEvent08 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUInterface object
  }//end main
}//end class SwingEvent08
//=======================================================//

//The following class is used to instantiate a user 
// interface object, to instantiate two Listener objects,
// and to register those two objects for notification 
// whenever a Window event occurs.
class GUI{
  public GUI(){//constructor
    //Create a new JFrame object
    JFrame displayWindow = new JFrame();
    displayWindow.setSize(300,200);
    displayWindow.setTitle("Copyright 1998, R.G.Baldwin");
    
    //Instantiate two Listener objects which will process
    // Window events
    WProc1 winProcCmd1 = new WProc1(displayWindow);
    WProc2 winProcCmd2 = new WProc2();
    
    //Register the Listener objects for notification of
    // Window events. This object is the Event Source.
    displayWindow.addWindowListener(winProcCmd1);
    displayWindow.addWindowListener(winProcCmd2);

    //windowActivated and windowOpened test messages
    // are produced here
    displayWindow.setVisible(true);

  }//end constructor
}//end class GUI definition
//=======================================================//

//The following two classes can be used to instantiate 
// Listener objects. Note that this class implements the 
// WindowListener interface.  This requires that all the
// methods declared in the interface be overridden in this
// class. This class overrides all of the methods  and
// displays a descriptive message whenever one of the
// methods is invoked.
class WProc1 implements WindowListener{
  //used to save a reference to the JFrame object
  JFrame displayWindowRef;
  
  WProc1(JFrame windowIn){//constructor
    // save ref to JFrame object
    this.displayWindowRef = windowIn;
  }//end constructor

  public void windowClosed(WindowEvent e){
    System.out.println("WProc1 windowClosed test msg");
  }//end windowClosed()
  
  public void windowIconified(WindowEvent e){
    System.out.println("WProc1 windowIconified test msg");
  }//end windowIconified()
  
  public void windowOpened(WindowEvent e){
    System.out.println("WProc1 windowOpened test msg");
  }//end windowOpened()

  public void windowClosing(WindowEvent e){
    System.out.println("WProc1 windowClosing test msg");
    displayWindowRef.dispose();//generate WindowClosed
  }//end windowClosing()

  public void windowDeiconified(WindowEvent e){
    System.out.println(
                      "WProc1 windowDeiconified test msg");
  }//end windowDeiconified()

  public void windowActivated(WindowEvent e){
    System.out.println("WProc1 windowActivated test msg");
  }//end windowActivated()

  public void windowDeactivated(WindowEvent e){
    System.out.println(
                     "WProc1 windowDeactivated test msg");
  }//end windowDeactivated()
}//end class WProc1
//=======================================================//

//This and the previous class can be used to instantiate 
// Listener objects. Note that this class extends an 
// Adapter class which can be used to avoid the 
// requirement to define all of the methods of the
// actual Listener class named WindowListener. This class
// overrides only two of the methods declared in the 
// interface.  It displays a message whenever one of the
// methods is invoked.
class WProc2 extends WindowAdapter{
  
  public void windowIconified(WindowEvent e){
    System.out.println(
              "******** WProc2 windowIconified test msg");
  }//end windowIconified()
  
  public void windowDeiconified(WindowEvent e){
    System.out.println(
            "******** WProc2 windowDeiconified test msg");
  }//end windowDeiconified()

}//end class WProc2

.  

Another Sample Program

This is a Swing version of the program named Event09.

The purpose of this program is to illustrate that in some cases, conversion of an AWT program to a Swing program isn't as simple as importing the Swing package and replacing the AWT components with their Swing counterparts.

That is what was done with this program.  This program is identical to the AWT program named Event09 except that all instances of Frame were replaced by JFrame and the Swing package was imported.

The intended behavior of this program (go back and review Event09 if necessary) is to display the coordinates of the mouse pointer each time that the mouse is clicked inside the client area of the JFrame.

Initially, this program appears to work correctly. However, as each new click occurs on the client area of the JFrame, a new pair of coordinate values is displayed, but the previous pairs of coordinate values does not disappear as is the case with the program named Event09.  Thus, the behavior is significantly different under JDK 1.1.6 and Swing 1.0.1 under Win95.

Furthermore, in some cases, while this GUI is on the screen, if focus is transferred to a different application, all of the coordinate values except the last one that was created will disappear.

It will be left as an exercise for the student to dig into the (currently very sparse) documentation on Swing in order to understand and explain this behavior.

As explained earlier, this lesson is concerned with event handling in Swing and this program is adequate to illustrate the use of the Delegation Event Model with Swing.  We will leave the subtle behavior of the Swing components for discussion in subsequent lessons.

If you compile and execute this program, whenever you click the mouse inside the JFrame, you should see the coordinates of the mouse pointer displayed above the mouse pointer.

SwingEvent09 Interesting Code Fragments

The only code fragment that will be highlighted is the one that illustrates how this program extends JFrame into a new class named MyFrame to make it possible to override the paint() method of the JFrame class. Recall that in the program named Event09, the Frame class was extended in a similar way.
 

class MyFrame extends JFrame{
  int clickX;
  int clickY;
  
  public void paint(Graphics g){
    g.drawString(
             "" + clickX + ", " + clickY, clickX, clickY);
  }//end paint()
}//end class MyFrame

 

SwingEvent09 Program Listing

This section contains a complete listing of the program.

/*File SwingEvent09.java Copyright 1998, R.G.Baldwin
Rev 5/9/98 by RGB
This is a Swing version of the program named Event09.

The purpose of this program is to illustrate that in some
cases, conversion of an AWT program to a Swing program
isn't as simple as importing the Swing package and replacing
the AWT components with Swing components.

That is what was done with this program.  In other words,
this program is identical to the AWT program named Event09
except that all instances of Frame were replaced by JFrame
and the Swing package was imported.

At the surface, the program appears to work correctly.
However, as each new click occurs on the client area of
the JFrame, a new pair of coordinate values is displayed,
but the previous pairs of coordinate values don't disappear
as is the case with the program named Event09.

Furthermore, in some cases, while this GUI is on the screen,
if focus is transferred to a different application, all of
the coordinate values except the last one created will 
disappear.

It will be left as an exercise for the student to dig into
the (currently very sparse) documentation on Swing in order
to understand and explain this behavior.

Illustrates the use of Event Sources, Event Listeners, and 
Adapters in the Delegation Event Model for Swing.

This program instantiates a Listener object to process 
mouse events. When a mouse press occurs in a JFrame object,
the program gets the coordinates and then displays those
coordinates near the point of the mouse press.

Tested using JDK 1.1.6 and Swing 1.0.1 under Win95.
**********************************************************/
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class SwingEvent09 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUI
  }//end main
}//end class SwingEvent09
//=======================================================//

//Subclass JFrame in order to override the paint method.
class MyFrame extends JFrame{
  int clickX;
  int clickY;
  
  public void paint(Graphics g){
    g.drawString(
             "" + clickX + ", " + clickY, clickX, clickY);
  }//end paint()
}//end class MyFrame
//=======================================================//

//The following class is used to instantiate a 
// graphical user interface object.
class GUI {
  public GUI(){//constructor
    //Create a new JFrame object, set size, title, etc.
    MyFrame displayWindow = new MyFrame();
    displayWindow.setSize(300,300);
    displayWindow.setTitle("Copyright 1998, R.G.Baldwin");
    displayWindow.setVisible(true);
    
    //Instantiate and register an anonymous Listener 
    // object which will terminate the program when the 
    // user closes the JFrame.
    displayWindow.addWindowListener(new WProc1());
    
    //Instantiate and register an anonymous Listener 
    // object that will process mouse events to determine
    // and display the coordinates when the user presses
    // the mouse button in the client area of the JFrame.
    displayWindow.addMouseListener(
                             new MouseProc(displayWindow));
  }//end constructor
}//end class GUI definition
//=======================================================//

//This listener class monitors for mouse presses and 
// displays the coordinates of the mouse pointer when the
// mouse is pressed on the source object. Note that this
// class extends is an adapter class.
class MouseProc extends MouseAdapter{
  MyFrame refToWin; //save a reference to the source here
  
  MouseProc(MyFrame inWin){//constructor
    refToWin = inWin;//save ref to window
  }//end constructor

  //Override the mousePressed method to determine and 
  // display the coordinates when the mouse is pressed.
  public void mousePressed(MouseEvent e){
    //Get X and Y coordinates of mouse pointer and store
    // in an instance variable of the JFrame object
    refToWin.clickX = e.getX();
    refToWin.clickY = e.getY();
    
    //Force the JFrame object to be repainted in order to
    // display the coordinate information.
    refToWin.repaint();
  }//end mousePressed()
}//end class MouseProc
//=======================================================//

//The following listener is used to terminate the program
// when the user closes the frame.  Note that this class
// extends an adapter class.
class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1
//=======================================================//

Summary

Swing provides a new set of lightweight components that can be programmed using the Delegation Event Model first introduced in JDK 1.1.

The Swing components cannot be programmed using the event model from JDK 1.0.

In some cases, all that is necessary to convert a program built around AWT components to a program built around Swing components is to import the Swing classes and replace all instances of AWT components with their Swing counterparts.

In other cases, a simple substitution as described above will not produce the same behavior.

Many of the new Swing components do not have an AWT counterpart. The Swing classes contain a number of new components that were never added to the AWT component library.

This lesson has dealt exclusively with the use of the Delegation Event Model for programming Swing components and has left some unanswered questions regarding how the behavior of Swing components does, and in some cases does not, mirror that of their AWT counterparts.

-end-