Java Programming Notes # 1852
- Preface
- Preview
-
Discussion and
Sample Code - Run the Program
- Summary
- What’s Next?
- Complete Program Listing
Preface
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:
- Defining new focus traversal keys
- How to control focusability at runtime.
- The ability to query for the currently focused Component.
- The default Focus Traversal Policy.
- How to establish a focus traversal policy and modify it at
runtime.
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.
Preview
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.
Discussion
and Sample Code
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.
- focusNextComponent(Component)
- focusPreviousComponent(Component)
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.
- transferFocus()
- transferFocusBackward()
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.
Run the Program
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.
Summary
In this lesson, I have taught you three different ways to implement
programmatic focus traversal in Java V1.4 or later.
What’s Next?
Future lessons will discuss new focus features of version 1.4
including the following:
- The KeyEventDispatcher interface
- The KeyEventPostProcessor interface
- FocusEvent and WindowEvent
- Event delivery
- Opposite components
- Temporary focus events
- Focus and PropertyChangeListener
- Focus and VetoableChangeListener
Complete Program Listing
A complete listing of the program discussed in this lesson is shown in
Listing 12.
/*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.
About the author
Richard Baldwin is a
college professor (at Austin Community College in Austin, TX) and
private consultant whose primary focus is a combination of Java, C#,
and XML. In addition to the many platform and/or language independent
benefits of Java and C# applications, he believes that a combination of
Java, C#, and XML will become the primary driving force in the delivery
of structured information on the Web.
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-