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

Event Handling in JDK 1.1, Building A Custom Focus-Traversal Method

Java Programming, Lecture Notes # 88, Revised 02/21/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.

The material in this lesson is very important. However, there is simply too much material to be covered in detail during lecture periods. Therefore, students in Prof. Baldwin's Intermediate Java Programming classes at ACC will be responsible for studying this material on their own, and bringing any questions regarding the material to class for discussion.

Introduction

This lesson is originally being written in February of 1997 using JDK 1.1, Beta 3.

Earlier lessons have discussed the requestFocus(), focusGained() and focusLost() events in the Delegation Event Model of JDK 1.1.

This lesson will implement a practical application of event handling using these methods.

Overview

Typical Windows program that provide a Graphical User Interface allow the user to move the focus through a set of visual components using the tab key. Typically, the shift-tab key will move the focus through the same set of components in reverse order. We will refer to this process as focus traversal.

JDK 1.1 supports focus traversal with no special effort on the part of the programmer. The order in which the focus moves through the components is apparently determined by the order in which the components are instantiated and apparently cannot be modified. (Other GUI development environments are often more flexible in this regard.)

Also the standard focus-traversal scheme automatically excludes some types of components from gaining the focus (a label for example). If there is a way to force the system to shift the focus to these components, I haven't discovered it yet. However, skipping certain types of components, such as labels, is fairly standard procedure within the industry.

The chances are good that in most cases, you will be satisfied with the standard focus-traversal method. However, the thesis behind this lesson is that you might not be satisfied with the standard focus-traversal scheme, and might want to implement your own focus-traversal scheme using a different key.

Even if you never want to do this, it provides a good illustration of the use of certain aspects of the Delegation Event Model in JDK 1.1.

This lesson will use the material learned in earlier lessons to implement a custom focus-traversal capability where the F12 and the Shift-F12 key can be used to move the focus through a series of visual components.

In this lesson, we will also cause those components which are normally skipped by the standard focus-traversal method to gain the focus.

Also, the order in which the focus moves through the components will be independent of the order in which the components are instantiated and will be based solely on logical decisions made at runtime.

The program will be structured such that a modest additional programming effort would make it possible to modify the order that the focus moves through the components at runtime.

In an earlier lesson, we demonstrated that whenever a component has the focus (including components such as Labels and Frames) those components will respond to keyboard input. In order to keep this program simple, we have eliminated that capability from the program.

Also in an earlier lesson, we demonstrated how to use mouse clicks to cause the focus to be shifted to the component that receives the click. Again, for simplicity, we have removed that capability from the program.

Obviously these capabilities which have been eliminated could be restored with a modest programming effort.

The Sample Program

This section will present a discussion of the program followed by the program listing.

Discussion

This program is fairly long, but it is also fairly repetitive which attests to the simplicity and consistency of the Delegation Event Model in JDK 1.1.

A Button object, a TextField object, and a Label object are placed in a Frame object.

Normally you cannot see the outline of a Label object, so its background color is made yellowso that it will show up in the white expanse of the Frame object.

Focus Event Processing

A FocusListener object is instantiated and registered to listen for focusGained() and focusLost() events on the Frame and the Label. When these events occur, the FocusListener object makes a color change on the Frame or the Label to provide a visual indication of focus gained or lost.

When the Label has the focus, its text is red. Otherwise, its text is black.

When the Frame has the focus, its background color is blue. Otherwise, it is white.

Note that the Button and the TextField components automatically provide a visual indication of focus, and they automatically receive the focus when clicked on without intervention by the programmer.

Keyboard Event Processing

A KeyListener object is instantiated and registered to listen for keyPressed() events on the Frame, Label, Button, and TextField objects.

Whenever a key is pressed, the object currently holding the focus generates a keyPressed() event, even if it is a type of object that we don't normally expect to respond to the keyboard (such as the Label).

If the F12 or Shift-F12 key is pressed, the KeyListener object implements a program-defined scheme to move the focus to the next or previous component in the sequence.

Unlike the standard focus-traversal method based on the Tab key, the determination of next and previous is independent of the order in which the components were instantiated.

Also unlike the standard focus-traversal method based on the Tab key, the Label and Frame components are included in the sequence.

Window Event Processing

Finally, a WindowListener object is instantiated and registered to terminate the program when the user closes the Frame object. We have used this type of event processing in previous lessons so there is nothing new here.

Program Listing

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

This program implements a custom scheme for moving the focus
among a set of visual components using the F12 key and the 
Shift-F12 key as an alternate to the Tab and Shift-Tab key.

The Tab and Shift-Tab key also work in the standard manner.
Tab and Shift-Tab are automatically implemented by the system, 
and skip the Label object and the Frame object when moving 
the focus.

This custom scheme based on the F12 key does not skip the 
Label object or the Frame object.

For simplicity, this program does not support response to
the keyboard while the component has the focus.  Such response
has been illustrated in earlier lessons and could be added 
with very little additional code.

A Button object, a TextField object, and a Label object are placed 
in a Frame object.

A FocusListener object is instantiated and registered to listen for
focusGained() and focusLost() events on the Frame and the
Label.  When these events occur, the listener object makes a color
change on the Frame or Label to provide a visual indication of focus
gained or lost.  

When the Label has the focus, its text is red.  Otherwise, its text 
is black.  When the Frame has the focus, its background color is blue.
Otherwise, it is white.

Note that the Button and the TextField components automatically provide 
a visual indication of focus without intervention by the programmer.

Also for simplicity, the ability to shift the focus to the Label and
the Frame using the mouse was not included in this program.  This
capability has been illustrated in an earlier lesson and could be added
with very little additional code required.

Note that the Button and the TextField automatically receive the
focus when clicked without intervention by the programmer.

A KeyListener object is instantiated and registered to listen for
keyPressed() events on the Frame, Label, Button, and TextField 
objects.  This object is used to listen for the F12 or Shift-F12
key and to implement the program-specified change in focus when
such a keypress occurs.

Finally, a WindowListener object is instantiated and registered to 
terminate the program when the user closes the Frame object.

This program retrieves and saves the component names that are 
automatically assigned to the visual components (under the assumption 
that the system will assign unique names) and uses those names to 
determine which component generated an event when such determination 
is necessary.

No attempt was made to synchronize this focus traversal method with
other capabilities to shift the focus.

These results were produced using JDK 1.1, Beta 3 running under 
Windows 95.
*/
//==========================================================================

import java.awt.*;
import java.awt.event.*;

public class Event16 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a Graphical User Interface object
  }//end main
}//end class Event16
//===========================================================================

//The following class is used to instantiate a graphical user interface object.
class GUI {
  String myTextFieldName; //save automatic component name here
  String myButtonName;
  String myFrameName;
  String myLabelName;
  Frame myFrame;//ref variable passed as parameter
  Label myLabel;
  TextField myTextField;
  Button myButton;
  int focusIndex;

  public GUI(){//constructor
    //Create several visual components
    myFrame = new Frame();
    myFrame.setSize(250,300);
    myFrame.setTitle("Copyright 1997, R.G.Baldwin");
    myFrameName = myFrame.getName();

    myButton = new Button("Button Object");
    myButtonName = myButton.getName();
    
    myTextField = new TextField("TextField Object");
    myTextFieldName = myTextField.getName();//save the name of the component

    myLabel = new Label("LabelObject");
    myLabelName = myLabel.getName();
    myLabel.setBackground(Color.yellow);//make it yellow so it will show up
  
    //Add the other objects to the frame using default border layout manager
    myFrame.add("North",myButton);
    myFrame.add("South",myTextField);
    myFrame.add("West",myLabel);
    
    myFrame.setVisible(true);//make the frame visible
    myTextField.requestFocus();//initialize the focus to the TextField
    focusIndex = 0;//set focusIndex to match

    //Instantiate and register a FocusListener object which will process
    // focus events on two different visual components.  In this case,
    // the listener object makes a color change on the visual component
    // to indicate focus gained or focus lost.
    myFocusListener focusHandler = new myFocusListener(this);
    myFrame.addFocusListener(focusHandler);  
    myLabel.addFocusListener(focusHandler);
    
    //Instantiate and register a KeyListener object which will process key
    // events on four different visual components.  This object causes the
    // focus to move in a program-defined manner when the user presses the
    // F12 key and to move in the reverse direction when the user presses
    // the Shift-F12 key.
    myKeyListener keyHandler = new myKeyListener(this);
    myFrame.addKeyListener(keyHandler);
    myTextField.addKeyListener(keyHandler);
    myButton.addKeyListener(keyHandler);
    myLabel.addKeyListener(keyHandler);    

    //Instantiate and register a WindowListener object which will terminate 
    // the program when the user closes the Frame object
    WProc1 winProcCmd1 = new WProc1();
    myFrame.addWindowListener(winProcCmd1);
  }//end constructor
}//end class GUI definition
//=======================================================================

//This is a low-level event listener class.
// This FocusListener class makes a color change on the component to 
// provide a visual indication of the gain or loss of focus.

class myFocusListener implements FocusListener{
  GUI thisObject;
  
  myFocusListener(GUI thisObjectIn){//constructor
    thisObject = thisObjectIn;
  }// end constructor
  
  public void focusGained(FocusEvent e){
    if( e.toString().indexOf("on " + thisObject.myFrameName) != -1 ){
      thisObject.myFrame.setBackground(Color.blue);
    }//end if
    if( e.toString().indexOf("on " + thisObject.myLabelName) != -1 ){
      thisObject.myLabel.setForeground(Color.red);
    }//end if
    thisObject.myFrame.repaint();
  }//end focusGained()

  public void focusLost(FocusEvent e){
    if( e.toString().indexOf("on " + thisObject.myFrameName) != -1 ){
      thisObject.myFrame.setBackground(Color.white);      
    }//end if       
    if( e.toString().indexOf("on " + thisObject.myLabelName) != -1 ){
      thisObject.myLabel.setForeground(Color.black);      
    }//end if       
    thisObject.myFrame.repaint();
  }//end focusLost()
}//end class myFocusListener
//=======================================================================

//This is a Low-Level event listener.
// This listener class implements a custom scheme for moving focus 
// among visual components when the user presses the F12 key or the 
// Shift-F12 key.  The F12 key moves the focus counter-clockwise on 
// the screen and includes the Label object and the Frame object in 
// the path.  Shift-F12 moves the focus in the reverse direction.

// The standard Tab and Shift-Tab keys work also but don't include 
// the Label object or the Frame object in the list of objects which 
// receive focus.

class myKeyListener extends KeyAdapter{
  GUI thisObject;
  
  myKeyListener(GUI thisObjectIn){//constructor
    thisObject = thisObjectIn;
  }//end constructor

  public void keyPressed(KeyEvent e){
    int keyCode = e.getKeyCode();
    if( (keyCode == KeyEvent.VK_F12) //if F12 and NOT Shift
          && (e.getModifiers() != InputEvent.SHIFT_MASK) ){
      //Move the focus counter-clockwise on the screen for F12 key
      if(++thisObject.focusIndex > 3) thisObject.focusIndex = 0;
      switch(thisObject.focusIndex){
        case 0: thisObject.myTextField.requestFocus(); break;
        case 1: thisObject.myLabel.requestFocus();break;
        case 2: thisObject.myButton.requestFocus();break;
        case 3: thisObject.myFrame.requestFocus();break;
      }//end switch statement
    }//end if statement

    if( (keyCode == KeyEvent.VK_F12) //if F12 AND Shift
          && (e.getModifiers() == InputEvent.SHIFT_MASK) ){
      //Move the focus clockwise on the screen for Shift-F12 key
      if(--thisObject.focusIndex < 0) thisObject.focusIndex = 3;
      switch(thisObject.focusIndex){
        case 0: thisObject.myTextField.requestFocus(); break;
        case 1: thisObject.myLabel.requestFocus();break;
        case 2: thisObject.myButton.requestFocus();break;
        case 3: thisObject.myFrame.requestFocus();break;
      }//end switch statement
    }//end if statement
  }//end keyPressed()
}//end class myKeyListener
//=======================================================================

//The following listener is used to terminate the 
// program when the user closes the Frame object.
class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1
This sample program implements a number of useful techniques involving the Delegation Event Model. You would be well-advised to make certain that you understand it.

Review

This entire lesson is a review of material covered in previous lessons. Therefore, no additional review material is provided in this section.

-end-