JavaFocusability in Java Version 1.4

Focusability in Java Version 1.4

Java Programming Notes # 1844


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 is the second lesson in a new miniseries that will
teach you how to use the features of the new focus subsystem.  The first lesson in the series was entitled
Focus
Traversal Policies in Java Version 1.4
.

During the lifetime of Java, few if any of the improvements included in new
versions have been incompatible with code written for previous versions. 
Unfortunately, that history of upgrade success changed with the release of the
new focus subsystem in V1.4.  Several aspects of the new subsystem are
incompatible with code written for previous versions.

Historical problems with the focus subsystem

According
to Sun,

"Prior to Java 2 Standard Edition, JDK 1.4, the AWT focus subsystem
was inadequate. It suffered from major design and API problems,
as well as over a hundred open bugs. Many of these bugs were caused by
platform inconsistencies, or incompatibilities between the native
focus system for heavyweights and the Java focus system for
lightweights."

What does Sun say about focus in V1.4?

Sun goes on to describe some of the specific problems and then states:

"To address these and other deficiencies, we have designed a new focus
model for the AWT in JDK 1.4. The primary design changes were the
construction of a new centralized KeyboardFocusManager class, and a
lightweight focus architecture."

Unfortunately, Sun also states,

"While we have
attempted to remain backward compatible with the existing
implementation, we were forced to make minor incompatible changes in
order to reach an elegant and workable conclusion. We anticipate that
these incompatibilities will have only a trivial impact on existing
applications."

KeyboardFocusManager

The KeyboardFocusManager class provides APIs that make it possible for
client code to:

  • Inquire about the current focus state
  • Initiate focus changes
  • Replace the default focus event dispatching with a custom dispatcher

I will be discussing each of these capabilities in the tutorial lessons in
this miniseries.  In addition, I will use the KeyboardFocusManager
class in the sample program in this lesson.

PropertyChangeListener

Clients can inquire about the focus state directly.  Alternatively, clients
can register a PropertyChangeListener to receive a PropertyChangeEvent
when a change to the focus state occurs.

I will also discuss these alternatives in the tutorial lessons in this
miniseries.

A lot to learn

There is a lot to learn
about the new focus subsystem.  It is anything but trivial.  This
lesson will deal with several aspects of the new focus subsystem, including:

  • How to control focusability at runtime.
  • The ability to query for the currently focused Component.
  • The default Focus Traversal Policy.

In addition, this lesson will show you how to write Swing programs that
exhibit the look and feel of the operating system being used.  While this
is not directly related to the new focus subsystem, it is good thing to know,
and this is an opportune time for me to explain it.

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.


General Background Information

Focusability

A focusable Component is a component that can become the focus owner and
participates in keyboard focus traversal with
a FocusTraversalPolicy.

Information from the previous lesson

The
first lesson in this series, entitled
Focus
Traversal Policies in Java Version 1.4
, contained a great deal of
important information, including descriptions of several important terms:

  • Focus traversal
  • The focus cycle root
  • Focus traversal cycle
  • Focus owner
  • Up cycle and down cycle
    traversal operations
  • Focus traversal policy

In addition, that lesson showed you how to establish a focus traversal
policy, and how to modify that policy at runtime.

It is strongly recommended
that you study that lesson before continuing with this
lesson.


Preview

The sample program that I will discuss in this lesson illustrates the
following:

  • How to control the focusability of individual components at runtime.
  • The ability to query for the currently focused Component.
  • The default Focus Traversal Policy for Swing.
  • The use of the OS look and feel with Swing.

Discussion
and Sample Code

Description of the program named Focusability01

A single JFrame object appears on the screen,
as shown in Figure 1.

Figure 1  The GUI at startup

Three JButton objects and a
JTextField object appear at the North, South, East, and Center locations in
the frame.

Program state at startup

When the program first starts running, the text field has the
focus and the button in the South location displays the word Focusable.

The focus traversal policy

The default focus traversal policy is in effect at startup (and throughout
the running of the program).
  Generally, this policy
causes the focus to traverse from left to right, top to bottom (I will
discuss this in more detail later).

Successive presses on the tab key
causes the focus to traverse these components in the following order:

  • Text field
  • Button 2
  • Button 1
  • Focusable button
  • Back up to the text field where the cycle repeats

Change focusability of the South button

When you click
Button2, the text and the color of the characters in the South button changes to
that shown in Figure 2.

Figure 2  The GUI after clicking Button2

More importantly, the South
button loses its ability to gain the focus when you click Button2.

The new focus traversal path

Successive presses on the tab
key causes the focus to traverse these components in the following order
(skipping the South button):

  • Text field
  • Button 2
  • Button 1
  • Back up to the text field where the cycle repeats

Toggle the focusability of the South button

Successive clicking on
Button2 causes the South button to toggle back
and forth between being focusable and not being focusable.

SDK Version 1.4 required

This program requires SDK V1.4 or later, because features used in this program
were first released in V1.4.

The program was tested using SDK 1.4.1 under WinXP

More detailed description of the program

The GUI uses Swing components and exhibits a
look and feel that is the standard look and feel
for the operating system under which the program
is running.

The program displays a frame object containing a
button at the South location of the frame, which is
initially labeled Focusable.  When this button
is labeled Focusable, it is part of the default
focus traversal path, which proceeds from the
top left to the bottom right in the GUI.

The focus traversal path

The previous lesson taught you how to establish the focus traversal path for
a graphical user interface.  If you don’t explicitly establish the
traversal path, a default focus traversal path will be used.

The default focus traversal path for Swing
components

The default traversal path is not the same for AWT components and Swing
components.  Here is what Sun has to say about the default traversal path
for Swing components:

“Swing applications, or mixed Swing/AWT
applications, that use one of the standard look
and feels, or any other look and feel derived
from BasicLookAndFeel, will use
LayoutFocusTraversalPolicy for all Containers by default."

The LayoutFocusTraversalPolicy

Here is part of what Sun has to say about the LayoutFocusTraversalPolicy:

"… Based on their size and position, Components are roughly
categorized into rows and columns. For a Container with horizontal orientation,
columns run left-to-right or right-to-left, and rows run top-to-bottom. … All
columns in a row are fully traversed before proceeding to the next row."

I did not explicitly define a focus traversal path for this program, so the
default focus traversal policy is in effect throughout the running of this
program.

The above quotation from Sun is a little cryptic, buy you should be able to pick out
enough information to understand why the default traversal path for this program
runs from left to right, top to bottom.

Toggling the focusability of the South button

The GUI also displays a button labeled Button2, as shown in Figure 1. 
Clicking this button toggles the text on the South button between Focusable and
Not Focusable.

When the South button is labeled
Not Focusable, the South button cannot receive
the focus.  It is not included in the focus
traversal path.  It does not receive the focus as a result of successively
pressing the tab key, and it does not receive the focus
when it is clicked with the mouse.

Not disabled for events

However, each
time the South button is clicked with the mouse, regardless of
whether it has or gets the focus, it fires
an ActionEvent.

(Not being focusable does not equate to being unable to fire events.)

Also, if the space bar is pressed while the South button has the focus, it fires
an ActionEvent.

The ActionEvent handler

The ActionEvent handler registered on the South button causes the text
“Button0 clicked” followed by the name of the
“Currently Focused Component" to be displayed.  Here is an example of such an output produced
by clicking the South button while Button2 has the focus and the South
button is not focusable:

Button0 clicked
Currently Focused Component: Button2

Other components

In addition to the two buttons discussed above,
the GUI also displays a text field and another
button as shown in Figure 1.  No listeners are registered on
either of those components.

Will discuss sample program in fragments

As usual, I will discuss the program in fragments.  You can view a listing
of the entire program in Listing 10 near the end of the lesson.

The main method

The program begins in Listing 1 where the main method simply
instantiates an object of the class named GUI.
 

public class Focusability01 {
  public static void main(String[] args){
    new GUI();
  }//end main
}//end class Focusability01

Listing 1

It is the class named GUI that produces the user interface shown in
Figures 1 and 2.

The class named GUI

The class named GUI, which extends JFrame, begins in Listing
2.
 

class GUI extends JFrame{
  JTextField textField;
  JButton button0;
  JButton button1;
  JButton button2;
  boolean button0isFocusable = true;

Listing 2

The class begins by declaring reference variables that will be used to hold
references to each of the components shown in Figure 1.

The code in Listing 2 also declares and initializes an instance variable that
will be used to hold the focusability state of the South button.  When this
variable is true, the button is focusable.  When this variable is false,
the button is not focusable.

The constructor

The constructor for the GUI class begins in Listing 3. 
 

  public GUI(){//constructor
    textField = new JTextField("Some text");
    button0 = new JButton("Focusable");
    button1 = new JButton("Button1");
    button2 = new JButton("Button2");

Listing 3

The code in Listing 3 instantiates the four components shown in Figure 1, and
saves those object’s references in the corresponding instance variables.

Give each component a name

Later on, a query will be performed to determine which component currently
has the focus.  The name of the currently focused component will be
displayed on the standard output device.

The code in Listing 4 sets the name property for each of the four
components to a unique value.

    textField.setName("Text Field");
    button0.setName("Button0");
    button1.setName("Button1");
    button2.setName("Button2");

Listing 4

The worst problem

Sun provides several reasons for releasing a new focus subsystem in V1.4, in
order to correct problems with the earlier focus subsystem.

According to Sun,

"The single worst problem with the earlier AWT focus implementation was the inability to query for the currently focused Component."

Code in the next fragment demonstrates that this problem has been solved in V1.4.

An action listener on the South button

Continuing with the code in the constructor, the code in Listing 5
registers an action listener on the South button.  The purpose of this
action listener is twofold:

  • Demonstrate that a button is capable of firing action events even when it
    is incapable of gaining the focus.
  • Show the syntax required to query for the currently focused component.
    button0.addActionListener(
                            new ActionListener(){
      public void actionPerformed(ActionEvent e){
        System.out.println("Button0 clicked");

        System.out.println(
                "Currently Focused Component: " +
                KeyboardFocusManager.
                getCurrentKeyboardFocusManager().
                getFocusOwner().getName());
      }//end actionPerformed
    });

Listing 5

Two print statements

The code in Listing 5 contains two print statements inside the
actionPerformed
method.  The first print statement simply displays the
fact that the South button was clicked.

The second print statement gets and displays the value of the name
property (set earlier) of the component that holds the focus when the
South button is clicked.

Toggle the focusability of the South button

Whether or not a component can gain the focus is determined by the value of
the focusable property of the component.  The code in Listing 6
registers an action listener on button2, which toggles the focusability
of the South button between true and false each time button2 is clicked.

    button2.addActionListener(
                            new ActionListener(){
      public void actionPerformed(ActionEvent e){
        if(button0isFocusable){
          button0isFocusable = false;
          button0.setForeground(Color.RED);
          button0.setText("Not Focusable");
          button0.setFocusable(false);
        }else{
          button0isFocusable = true;
          button0.setForeground(Color.BLACK);
          button0.setText("Focusable");
          button0.setFocusable(true);
        }//end else
      }//end actionPerformed
    });

Listing 6

Focusable

When the value of the focusable property is set to true, the South
button is included in the focus traversal path, and also gains the focus when it
is clicked by the mouse.

Not focusable

When the value of the focusable property is set to false, the South
button is unable to gain the focus.  It is removed from the focus traversal
path, and also doesn’t gain the focus when clicked by the mouse.

Finish constructing the GUI

The code in Listing 7 sets the size and the title of the frame.
 

    setSize(250,120);
    setTitle("Copyright 2003 R.G.Baldwin");

    //Add objects to the frame using default
    // border layout manager.  Do not add in same
    // order as default focus traversal order.
    getContentPane().add(button0,"South");
    getContentPane().add(textField,"North");
    getContentPane().add(button1,"East");
    getContentPane().add(button2,"Center");

Listing 7

In addition, the code in Listing 7 adds the four components to the frame.

Note the addition order of the components

Note that the components were purposely added to the frame in an order that
is different from the default focus traversal path.  This demonstrates that
under the new focus subsystem, the default focus traversal path for Swing
components is independent of the order in which the components are added to the
container.

Set the look and feel

If you don’t set the look and feel when you create a Swing GUI, the default
look and feel will be the look and feel sometimes known as the metal
look and feel or the Java look and feel.

That may not be what you
want.  You may want the look and feel to match the native look and feel
for the current operating system.
 

    String plafClassName =
       UIManager.getSystemLookAndFeelClassName();

    try{
       UIManager.setLookAndFeel(plafClassName);
    }catch(Exception ex){System.out.println(ex);}

    //Cause the L&F to become visible.
    SwingUtilities.updateComponentTreeUI(this);

Listing 8

Get and use look and feel for current operating
system

The code in Listing 8 gets and uses the look and feel for the current
operating system without a requirement for the programmer to know the current
operating system (provided that Java supports a look and feel for that
operating system).

Odds and ends

The code in Listing 9 takes care of a couple more odds and ends, closes the
constructor, and closes the definition of the GUI class.

    setVisible(true);//make the frame visible
    setDefaultCloseOperation(
                           JFrame.EXIT_ON_CLOSE);
  }//end constructor
}//end class GUI definition

Listing 9

Run the Program

I encourage you to copy the code from Listing 10 into your text editor, compile it, and execute it.  Experiment
with it, making changes, and observing the results of your changes.

Remember, however, that you must be running Java V1.4 or later
to compile and execute this program, because it makes use of Java features that
were first released in V1.4.

Summary

In this lesson, I have taught you:

  • How to control the focusability of individual components at runtime.
  • How to query for the currently focused Component.
  • About the default Focus Traversal Policy for Swing.
  • How to use the OS look and feel with Swing.

What’s Next?

As time goes on, I plan to publish additional lessons that will help
you learn to use other features of the new focus subsystem.  Future lessons will discuss new focus features of version 1.4
including:

  • The KeyEventDispatcher interface
  • The KeyEventPostProcessor interface
  • FocusEvent and WindowEvent
  • Event delivery
  • Opposite components
  • Temporary focus events
  • Programmatic focus traversal
  • Focus and PropertyChangeListener
  • Focus and VetoableChangeListener

Complete Program Listing


A complete listing of the program discussed in this lesson is shown in Listing
10 below.

 

/*File Focusability01.java
Copyright 2003 R.G.Baldwin

This program illustrates:
1. How to control focusability at runtime.
2. The ability to query for the currently
   focused Component.
3. Default Focus Traversal Policy
4. Use of the OS look and feel with Swing.

The behavior of the program is as follows:

The GUI uses Swing components and exhibits a
look and feel that is the standard look and feel
for the operating system under which the program
is running.

The program displays a frame object containing a
button at the bottom of the frame, which is
initially labeled Focusable.  While this button
is labeled Focusable, it is part of the default
focus traversal path, which proceeds from the
top left to the bottom right in the GUI.

The GUI also displays a button labeled button2.
Clicking this button toggles the text on the
bottom button between Focusable and
Not Focusable.  When the bottom button is labeled
Not Focusable, the bottom button does not receive
the focus.  It is not included in the focus
traversal path, and it does not receive the focus
when it is clicked with the mouse.  However, each
time it is clicked with the mouse, regardless of
whether or not it has or gets the focus, it fires
an ActionEvent, which causes the text
"Button0 clicked" followed by the name of the
"Currently Focused Component "to be displayed on
the Standard Output Device.

In addition to the two buttons discussed above,
the GUI also displays a text field and another
button.  No active listeners are registered on
either of these components.

Requires Java SDK V1.4 or later.
Tested using JDK 1.4 under WinXP
************************************************/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Focusability01 {
  public static void main(String[] args){
    new GUI();
  }//end main
}//end class Focusability01

//=============================================//

class GUI extends JFrame{
  JTextField textField;
  JButton button0;
  JButton button1;
  JButton button2;
  boolean button0isFocusable = true;

  public GUI(){//constructor
    //Create several visual components
    textField = new JTextField("Some text");
    button0 = new JButton("Focusable");
    button1 = new JButton("Button1");
    button2 = new JButton("Button2");

    textField.setName("Text Field");
    button0.setName("Button0");
    button1.setName("Button1");
    button2.setName("Button2");

    //Register an action listener on button0 to
    // show that button0 fires action events even
    // when it is not focusable.
    button0.addActionListener(
                            new ActionListener(){
      public void actionPerformed(ActionEvent e){
        System.out.println("Button0 clicked");
        //According to Sun,  The single worst
        // problem with the earlier AWT focus
        // implementation was the inability to
        // query for the currently focused
        // Component.  The following statement
        // demonstrates that the problem has
        // been solved in V1.4.
        System.out.println(
                "Currently Focused Component: " +
                KeyboardFocusManager.
                getCurrentKeyboardFocusManager().
                getFocusOwner().getName());
      }//end actionPerformed
    });

    //Register an action listener on button2 to
    // toggle focusability of button0.
    button2.addActionListener(
                            new ActionListener(){
      public void actionPerformed(ActionEvent e){
        if(button0isFocusable){
          button0isFocusable = false;
          button0.setForeground(Color.RED);
          button0.setText("Not Focusable");
          button0.setFocusable(false);
        }else{
          button0isFocusable = true;
          button0.setForeground(Color.BLACK);
          button0.setText("Focusable");
          button0.setFocusable(true);
        }//end else
      }//end actionPerformed
    });

    setSize(250,120);
    setTitle("Copyright 2003 R.G.Baldwin");

    //Add objects to the frame using default
    // border layout manager.  Do not add in same
    // order as default focus traversal order.
    getContentPane().add(button0,"South");
    getContentPane().add(textField,"North");
    getContentPane().add(button1,"East");
    getContentPane().add(button2,"Center");

    //Set L&F to op syst being used
    String plafClassName =
       UIManager.getSystemLookAndFeelClassName();

    try{
       UIManager.setLookAndFeel(plafClassName);
    }catch(Exception ex){System.out.println(ex);}

    //Cause the L&F to become visible.
    SwingUtilities.updateComponentTreeUI(this);
    setVisible(true);//make the frame visible
    setDefaultCloseOperation(
                           JFrame.EXIT_ON_CLOSE);
  }//end constructor

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

Listing 10

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.

Baldwin@DickBaldwin.com

-end-

 

Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.
Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.

Latest Posts

Related Stories