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.
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.
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.
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.
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.
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.
/*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 |
-end-