Published: October 7, 2003
By Richard G. Baldwin
Java Programming Notes # 1852
New features in SDK Version 1.4.0
The recently released JavaTM 2 SDK, Standard Edition Version 1.4 contains a large number of new features, including many changes and additions to the focus subsystem. This lesson is part of a series of lessons designed to teach you how to use the new features of the focus subsystem in Java Version 1.4 and later.
The first lesson in the series was entitled Focus Traversal Policies in Java Version 1.4. The previous lesson was entitled Changing Focus Traversal Keys in Java V1.4.
Previous topics
Previous lessons have dealt with several aspects of the new focus subsystem, including:
This lesson deals with writing program code to control the focus.
Viewing tip
You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth among the different listings and figures while you are reading about them.
Supplementary material
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at www.DickBaldwin.com.
In this lesson, I will show you three different ways to control the focus programmatically. One way will cause the focus to traverse components according to the focus traversal policy, relative to the current focus owner.
The second way will cause the focus to traverse components according to the focus traversal policy, but relative to a specified component. I will show you two different ways to accomplish this.
The third way will cause a specified component to gain the focus.
Focus traversal
Sun defines focus traversal as "the user's ability to change the "focus owner" without moving the cursor."
Focus traversal can normally be either forward to the next component, or backward to the previous component.
Traversal typically uses keys
Typically, focus traversal is accomplished using one or more keys on the keyboard. For example, it is very common for the TAB key to be used to move the focus along its traversal path in the forward direction, and for the Shift-TAB key combination to be used to move the focus along its traversal path in the backward direction.
Keyboard is not required
However, keyboard action isn't always required. It is also possible for program code to initiate traversal through the execution of program instructions. That is the primary topic of this lesson.
FocusTraversalPolicy
The AWT focus implementation determines which component to focus next based on the FocusTraversalPolicy of the focus owner's focus cycle root. (The FocusTraversalPolicy was the subject of a previous lesson.)
Description of the program
This lesson presents a program named FocusTraversal02 that illustrates three different ways to control the focus programmatically.
The graphical user interface
The program displays the graphical user interface (GUI) shown in Figure 1.
Figure 1. Sample program user interface.
The numbers on a clock
A single JFrame object appears on the screen. Four JButton objects appear at the North, South, East, and West locations in the frame. The buttons display the captions 03, 06, 09, and 12.
(The positions of the buttons with their captions mimic four of the numbers on a clock.)
Three JLabel objects
Three JLabel objects with labels A, B, and C appear in the center of the frame.
Keyboard-generated focus traversal
When the program first starts running, the button with the caption 12 has the focus.
Successively pressing the TAB key causes the focus to traverse the buttons in a clockwise direction: 12, 03, 06, 09 and back to 12.
Holding down the Shift key and successively pressing the TAB key causes the focus to traverse the buttons in a counter-clockwise direction: 12, 09, 06, 03, and back to 12.
(The traversal path described above illustrates the use of a custom focus traversal policy, which was discussed in an earlier lesson.)
Programmatic focus traversal
This program also supports programmatic focus traversal based on mouse clicks. Successively clicking the A in the center of the frame (see Figure 1) causes the same traversal result as successively pressing the TAB key.
Holding down the Shift key and successively clicking the A causes the same result as holding down the Shift key and successively pressing the TAB key.
In other words, the result of clicking the letter A replicates the pressing of the TAB key. This illustrates programmatic focus traversal.
Moving the focus to a specific component
Clicking the letter B causes the button with the 12 to gain the focus.
Traversal relative to a specific component
The result of clicking the letter C is somewhat more difficult to explain. This causes the next component following the button with the 12 in the focus traversal policy (the button with the 03) to gain the focus.
Holding down the Shift key and clicking the letter C causes the previous component before the button with the 12 in the focus traversal policy (the button with the 09) to gain the focus.
In other words, clicking the letter C causes the same behavior that would occur from pressing the TAB key when the button with the 12 already has the focus.
Requires Version 1.4 or later
This program requires SDK V1.4 or later. It was tested using SDK 1.4.1 under WinXP
Will discuss sample program in fragments
As is my habit, I will discuss the program in fragments. A complete listing of the program is provided in Listing 12 near the end of the lesson.
Get a GUI object
Listing 1 shows the main method, which simply instantiates a new object of the GUI class. The graphical user interface shown in Figure 1 is a visual manifestation of that object.
public class FocusTraversal02 { |
The GUI class
Listing 2 shows the beginning of the GUI class, including the declaration of several instance variables. The purpose of these instance variables will be become clear as the discussion progresses.
class GUI extends JFrame{ |
The constructor
Listing 3 shows the beginning of the constructor for the GUI class.
public GUI(){//constructor |
All of the code in Listing 3 is straightforward, so I won't discuss it further. If you are unfamiliar with this code, see the other lessons on my web site.
The focus traversal policy
Listing 4 shows an abbreviated version of an inner class from which a FocusTraversalPolicy object will be instantiated to control the focus traversal policy for the frame. (You can view this class definition in its entirety in Listing 12 near the end of this lesson.)
class TrvslPolicy |
I discussed a class very similar to this one in the lesson entitled entitled Focus Traversal Policies in Java Version 1.4, so I won't discuss this class further in this lesson.
A focus traversal policy based on this class causes the focus to traverse the buttons in Figure 1 in a clockwise manner.
Set the focus traversal policy
Continuing with the constructor, the code in Listing 5 uses the
inner class defined above to establish the focus traversal policy for
the frame. The code in Listing 5 also makes the frame visible.
final TrvslPolicy policy = new TrvslPolicy(); |
Now for the new and interesting material
The next several code fragments will register mouse listeners on the labels showing A, B, and C in the center of Figure 1, to provide the programmatic focus traversal behavior described earlier.
A mouse listener on the label with an A
The code in Listing 6 uses an anonymous inner class to define, instantiate, and register a mouse listener on the label showing the A in the center of the frame in Figure 1.
labelA.addMouseListener( |
The purpose of this mouse listener is to replicate the focus traversal behavior of the TAB key when the user clicks on the A.
(Recall that the focus traversal behavior of the TAB key depends or whether or not the user is holding down the Shift key when the TAB key is pressed.)
Get the Shift key state
Listing 6 shows the beginning of the definition of the mousePressed event handler method. The code in Listing 6 gets and saves an int value that can be used to determine if the Shift key was being held down when the user clicked the label with the A.
(If the Shift key was not being held down, the value of shift in Listing 6 will be zero. If the Shift key was being held down, the value of shift will not be zero.)
Focus next component
If the Shift key was not being held down, the code in Listing 7 causes the focus to move to the next component (relative to the current focus owner) as specified by the focus traversal policy.
(This replicates the behavior of pressing the TAB key without holding down the Shift key.)
if(shift == 0){ |
The focusNextComponent method
This is accomplished by invoking the focusNextComponent method of the KeyboardFocusManager class. However, there is a little more to it than that. This is not a static method. Therefore, it is necessary to get access to the KeyboardFocusManager object currently in effect.
What is the KeyboardFocusManager?
Here is part of what Sun has to say about the KeyboardFocusManager class.
"The KeyboardFocusManager is responsible for managing the active and focused Windows, and the current focus owner. The focus owner is defined as the Component in an application that will typically receive all KeyEvents generated by the user. ...
The KeyboardFocusManager is both a centralized location for client code to query for the focus owner and initiate focus changes, and an event dispatcher for all FocusEvents, WindowEvents related to focus, and KeyEvents."
KeyboardFocusManager is an abstract class
You cannot instantiate an object of the KeyboardFocusManager class because it is abstract. You probably wouldn't want to anyway, because you wouldn't know how to assign the responsibilities described in the above quotation to the new object.
The getCurrentKeyboardFocusManager method
However, the KeyboardFocusManager class provides a static method named getCurrentKeyboardFocusManager, which, according to Sun,
"Returns the current KeyboardFocusManager instance for the calling thread's context."
Focus next component
As you can see in Listing 7, this is what we need in order to invoke the focusNextComponent method and move the focus to the next component specified by the focus traversal policy.
Focus previous component
Listing 8 shows the else clause of the if-else statement that was begun in Listing 7.
}else{ |
The code in Listing 8 is executed if the user was holding down the Shift key when the label with the A was clicked.
In this case, the method named focusPreviousComponent is invoked on the current keyboard focus manager. This causes the focus to move to the component that appears before the current focus owner in the focus traversal policy.
Again, this replicates the focus traversal behavior of holding down the Shift key and pressing the TAB key.
The requestFocus method
Java has had a method named requestFocus since long before the release of V1.4. However, here is part of what Sun has to say about that method in the documentation for V1.4.
"Requests that this Component get the input focus, and that this Component's top-level ancestor become the focused Window. ...
Because the focus behavior of this method is platform-dependent, developers are strongly encouraged to use requestFocusInWindow when possible."
The requestFocusInWindow method
Here is part of what Sun has to say about the requestFocusInWindow method.
"Requests that this Component get the input focus, if this Component's top-level ancestor is already the focused Window. ...
The focus behavior of this method can be implemented uniformly across platforms, and thus developers are strongly encouraged to use this method over requestFocus when possible."
Request focus on the button with the 12
The code in Listing 9 registers a mouse listener on the label showing the B. The purpose of this listener is to move the focus to the button in the twelve o'clock position in Figure 1 whenever the user clicks on the label with the B.
labelB.addMouseListener( |
As you can see, the change in focus is accomplished by invoking the requestFocusInWindow method on that button's reference whenever the mousePressed event handler method is executed.
Focus relative to a specified component
In addition to providing programmatic focus traversal relative to the current focus owner, V1.4 also provides programmatic focus traversal relative to a specified component, as though that component were the current focus owner.
This is accomplished by invoking the following methods of the KeyboardFocusManager class and specifying a component as a parameter to the method.
These methods differ from the methods used in Listings 7 and 8 in that each of these methods accepts a reference to a component as an incoming parameter.
Each of these methods initiates the traversal operation with the specified component rather than with the current focus owner. The traversal occurs as though the specified component is the current focus owner. However, the specified component need not be the current focus owner.
An alternative approach
The following alternate but equivalent methods are defined in the Component class.
As with the methods of the KeyboardFocusManager class, each of these methods initiates the traversal operation as though the component on which the method is invoked is the focus owner. Again, it is not necessary that the component be the focus owner.
As you will see in the upcoming fragments, these two methods require a little less typing than the equivalent versions discussed above.
Focus relative to the label with the C
Listing 10 registers a mouse listener on the label with the C in the center of the frame in Figure 1. This event handler initiates a focus traversal operation relative to the button in the twelve o'clock position in Figure 1, regardless of the current focus owner.
(The code in Listing 12 also shows the alternative, but equivalent method that can be used to accomplish the focus traversal.)
labelC.addMouseListener( |
Shift key not being held down
The code in Listing 10 is executed whenever the user clicks on the label with the C while not holding down the Shift key. This code invokes the focusNextComponent(Component) method of the KeyboardFocusManager class, passing a reference to the button in the twelve o'clock position as a parameter.
This causes the focus to move to the next component following that button in the focus traversal policy (the button at the three o'clock position in Figure 1).
The alternative method
The alternative method for accomplishing the same thing is shown by the last line in Listing 10, which has been turned into a comment. Note that the alternative method requires considerably less typing than the method that was actually used in Listing 10.
Shift key being held down
Listing 11 shows the code that is executed if the Shift key is being
held down when the user clicks the label with the C in the center of
the frame in Figure 1.
}else{ |
Both alternative methods are shown
Again, both of the alternative methods are shown in Listing 11. In this case, however the simpler method from the Component class is used, and the method from the KeyboardFocusManager class is turned into a comment.
In this case, the transferFocusBackward method is invoked on the reference to the button at the twelve o'clock position in Figure 1. This causes the button immediately before the button at the twelve o'clock position in the focus traversal policy (the button in the nine o'clock position in Figure 1) to gain the focus.
End of constructor and class
The code in Listing 11 also signals the end of the constructor and the end of the definition of the class named GUI.
If you haven't already done so, I encourage you to copy the code
from Listing 12 into your text editor, compile it, and execute
it. Experiment with it, pressing buttons and keys, and observing
the results of your actions.
Remember, however, that you must be running Java version 1.4 or later to compile and execute this program.
In this lesson, I have taught you three different ways to implement programmatic focus traversal in Java V1.4 or later.
Future lessons will discuss new focus features of version 1.4 including the following:
/*File FocusTraversal02.java |
Copyright 2003, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
Richard has participated in numerous consulting projects, and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.
-end-