August 28, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

The Opposite Focus Component

  • November 9, 2004
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Java Programming, Notes # 1854


Preface

The focus subsystem

When JavaTM 2 SDK, Standard Edition Version 1.4 was released, it contained a large number of new features.  This included many changes and additions to the focus subsystem. 

Changes to the focus subsystem represented a major departure from previous versions of Java.  Unfortunately, some of the changes caused Java code that had compiled and run successfully under previous versions of the SDK to fail under the new version.

This lesson is part of a series of lessons designed to teach you how to use the new features of the focus subsystem.

The first lesson in the series was entitled Focus Traversal Policies in Java Version 1.4.  The previous lesson was entitled Programmatic Focus Traversal in Java V1.4.

Previous topics

Previous lessons in this series 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.
  • How to control the focus programmatically.

This lesson will show you how to write code to get the opposite focus component.

Background information

Before getting into the technical details, I will provide some quotations from Sun that justify this new feature.  In discussing the changes to the focus subsystem, Sun has this to say:

"... many developers noted that the APIs for FocusEvent and WindowEvent were insufficient because they did not provide a way for determining the "opposite" Component involved in the focus or activation change. For example, when a Component received a FOCUS_LOST event, it had no way of knowing which Component was gaining focus. Since Microsoft Windows provides this functionality for free, developers migrating from Microsoft Windows C/C++ or Visual Basic to Java had been frustrated by the omission."

While discussing focus event delivery, Sun tells us:

"Each event includes information about the "opposite" Component or Window involved in the focus or activation change. For example, for a FOCUS_GAINED event, the opposite Component is the Component that lost focus. If the focus or activation change occurs with a native application, with a Java application in a different VM or context, or with no other Component, then the opposite Component or Window is null. This information is accessible using FocusEvent.getOppositeComponent or WindowEvent.getOppositeWindow.

On some platforms, it is not possible to discern the opposite Component or Window when the focus or activation change occurs between two different heavyweight Components. In these cases, the opposite Component or Window may be set to null on some platforms, and to a valid non-null value on other platforms. However, for a focus change between two lightweight Components which share the same heavyweight Container, the opposite Component will always be set correctly. Thus, a pure Swing application can ignore this platform restriction when using the opposite Component of a focus change that occurred within a top-level Window."

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 figures and listings 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 how to use a feature of the focus subsystem to find the opposite component when a particular component gains or loses the focus.

If that particular component gains the focus, the opposite component is the component that lost the focus.

If that particular component loses the focus, the opposite component is the component that gained 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.

Description of the program

This lesson presents and explains a program named FocusOpposite01.

This program illustrates the ability to programmatically determine the opposite component on a focusGained or focusLost event.

The program GUI

The program causes a single JFrame object to appear on the screen as shown in Figure 1.



Figure 1 Screen display.

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.)

Two JLabel objects appear in the center of the frame.  These labels are used to display focus information regarding the button in the twelve o'clock position.

Keyboard focus traversal

When the program first starts running, the button with the caption 12 has the focus, and the default focus policy applies.  According to the default focus policy, successively pressing the tab key causes the focus to traverse the buttons left to right, top to bottom.  Thus, the forward focus traversal path is as follows:  12, 09, 03, 06, and back to 12.

Holding down the Shift key and successively pressing the tab key causes the focus to traverse the buttons in the reverse direction.

Clicking any of the four buttons with the mouse causes it to gain the focus.

When button 12 gains the focus ...

Each time the button in the twelve o'clock position gains the focus for any reason, the "opposite" component that lost the focus is identified in one of the labels in the center of the frame.

The fact that the button in the twelve o'clock position gained the focus is also indicated in the center of the frame.

When button 12 loses the focus ...

Each time the button in the twelve o'clock position loses the focus for any reason, the "opposite" component that gained the focus is identified in one of the labels in the center of the frame.

The fact that the button in the twelve o'clock position lost the focus is also indicated in the center of the frame.

SDK V1.4 or later is required

This program requires SDK V1.4 or later to run correctly.  It was tested using SDK 1.4.2 under WinXP.

Will discuss in fragments

I will discuss this program in fragments.  A complete listing of the program is provided in Listing 6 near the end of the lesson.

Listing 1 shows the entire class named FocusOpposite01, including the main method.

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

Listing 1

The code in Listing 1 instantiates a new object of the GUI class.  This object produces the screen display shown in Figure 1.

The GUI class

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

class GUI extends JFrame{
  JLabel labelA = new JLabel(
                          "Display output here");
  JLabel labelB = new JLabel("");
  JPanel panel = new JPanel();
  JButton button12 = new JButton("12");
  JButton button03 = new JButton("03");
  JButton button06 = new JButton("06");
  JButton button09 = new JButton("09");
  JFrame frame = this;

Listing 2

The code in Listing 2 instantiates several buttons and other components required to construct the GUI object shown in Figure 1.

Listing 2 also creates a reference variable of type JFrame named frame and initializes it with a reference to the GUI object.

The GUI constructor

The constructor for the GUI class begins in Listing 3.

  public GUI(){//constructor
    setSize(250,100);
    setTitle("Copyright 2004, R.G.Baldwin");
    setDefaultCloseOperation(
                           JFrame.EXIT_ON_CLOSE);

    getContentPane().add(button12,"North");
    getContentPane().add(button03,"East");
    getContentPane().add(button06,"South");
    getContentPane().add(button09,"West");
    panel.add(labelA);
    panel.add(labelB);
    getContentPane().add(panel);

    frame.setVisible(true);

Listing 3

The code in Listing 3 places each of the components in the JFrame in order to construct the GUI object.  Then the code in Listing 3 causes the GUI object to become visible on the screen.

An anonymous focus listener class

Listing 4 shows the beginning of an anonymous inner class that is used to register a focus listener on the button at twelve o'clock.

(If you are unfamiliar with the use of anonymous inner classes for listener registration, you will find other tutorial lessons that explain that concept on my web site.)

    //Register focus listener on the twelve
    //o'clock button
    button12.addFocusListener(
      new FocusListener(){
        public void focusGained(FocusEvent e){
          labelA.setText("");
          labelB.setText("");
          Component lost =
                        e.getOppositeComponent();
          if(lost != null && lost instanceof
                                        JButton){
            labelA.setText("Lost: " +
                           ((JButton)lost).
                             getActionCommand());
          }//end if

          Object gained = e.getSource();
          if(gained != null && gained instanceof
                                        JButton){
            labelB.setText("Gained: " +
                           ((JButton)gained).
                             getActionCommand());
          }//end if
        }//end focusGained

Listing 4

The focusGained event handler method

Listing 4 shows the entire definition for the focusGained event handler method.

The one thing in Listing 4 that is new to this lesson is the invocation of the getOppositeComponent method on the incoming FocusEvent object.  The getOppositeComponent method returns a reference to the component that lost the focus when the button at twelve o'clock gained the focus.

What does Sun have to say?

Sun has this to say about the getOppositeComponent method:

"Returns the other Component involved in this focus change.

For a FOCUS_GAINED event, this is the Component that lost focus.

For a FOCUS_LOST event, this is the Component that gained focus.

If this focus change occurs with a native application, with a Java application in a different VM or context, or with no other Component, then null is returned."

The remaining code in focusGained ...

The remaining code in the focusGained method in Listing 4:

  • Gets a reference to the object that gained the focus.
  • Confirms that neither that reference nor the reference to the opposite component is null.
  • Confirms that both references refer to objects of type JButton
  • Displays the identification of the button that gained the focus and the button that lost the focus in the labels in the center of the frame.

The focusLost event handler method

Listing 5 shows the remaining code in the anonymous focus listener class.

        public void focusLost(FocusEvent e){
          labelA.setText("");
          labelB.setText("");
          Object lost = e.getSource();
          if(lost != null && lost instanceof
                                        JButton){
            labelA.setText("Lost: " +
                           ((JButton)lost).
                             getActionCommand());
          }//end if

          Component gained =
                        e.getOppositeComponent();
          if(gained != null && gained instanceof
                                        JButton){
            labelB.setText("Gained: " +
                           ((JButton)gained).
                             getActionCommand());
          }//end if
        }//end focusLost
      }//end new FocusListener
    );//end addFocusListener

  }//end constructor
}//end GUI

Listing 5

Listing 5 contains the entire focusLost event handler method. 

Behavior of the focusLost method

The behavior of the focusLost method is essentially the reverse of the behavior of the focusGained method shown in Listing 4.

Whenever the button at twelve o'clock loses the focus, the code in the focusLost method invokes the getOppositeComponent method to identify the component that gained the focus.

Then both components are displayed in the labels in the center of the frame.

End of constructor and GUI class

Listing 5 also signals the end of the constructor for the GUI class and the end of the GUI class.

Run the Program

I encourage you to copy, compile, and run the program provided in this lesson.  Experiment with it, making changes and observing the results of your changes.

Summary

I showed you how to use a feature of the focus subsystem to find the opposite component when a particular component gains or loses the focus.

If that particular component gains the focus, the opposite component is the component that lost the focus.

If that particular component loses the focus, the opposite component is the component that gained the focus.

What's Next?

Future lessons will discuss other focus features including the following:

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

Complete Program Listing

A complete listing of the program discussed in this lesson is provided below.

/*File FocusOpposite01.java
Copyright 2004 R.G.Baldwin

This program illustrates the ability to determine
the opposite component on a focusGained or
focusLost event.

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.)

Two blank JLabel objects appear in the center of
the frame.  These labels are used to display
focus information regarding the button in the
twelve o'clock position.

When the program first starts running, the
button with the caption 12 has the focus.

The default focus policy applies.  Successively
pressing the tab key causes the focus to
traverse the buttons left to right, top to
bottom:  12, 09, 03, 06, and back to 12.

Holding down the Shift key and successively
pressing the tab key causes the focus to traverse
the buttons in the reverse direction.

Each time the button in the twelve o'clock
position gains the focus for any reason, the
"opposite" component that lost the focus is
identified in one of the labels in the center
of the frame.  The fact that the button in the
twelve o'clock position gained the focus is also
indicated in the other label in the center of
the frame.

Each time the button in the twelve o'clock
position loses the focus for any reason, the
"opposite" component that gained the focus is
identified in one of the labels in the center
of the frame.  The fact that the button in the
twelve o'clock position lost the focus is also
indicated in the other label in the center of
the frame.

Requires SDK V1.4 or later.  Tested using
SDK 1.4.2 under WinXP
************************************************/

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

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

class GUI extends JFrame{
  JLabel labelA = new JLabel(
                          "Display output here");
  JLabel labelB = new JLabel("");
  JPanel panel = new JPanel();
  JButton button12 = new JButton("12");
  JButton button03 = new JButton("03");
  JButton button06 = new JButton("06");
  JButton button09 = new JButton("09");
  JFrame frame = this;

  public GUI(){//constructor
    setSize(250,100);
    setTitle("Copyright 2004, R.G.Baldwin");
    setDefaultCloseOperation(
                           JFrame.EXIT_ON_CLOSE);

    getContentPane().add(button12,"North");
    getContentPane().add(button03,"East");
    getContentPane().add(button06,"South");
    getContentPane().add(button09,"West");
    panel.add(labelA);
    panel.add(labelB);
    getContentPane().add(panel);

    frame.setVisible(true);

    //Register focus listener on the twelve
    //o'clock button
    button12.addFocusListener(
      new FocusListener(){
        public void focusGained(FocusEvent e){
          labelA.setText("");
          labelB.setText("");
          Component lost =
                        e.getOppositeComponent();
          if(lost != null && lost instanceof
                                        JButton){
            labelA.setText("Lost: " +
                           ((JButton)lost).
                             getActionCommand());
          }//end if

          Object gained = e.getSource();
          if(gained != null && gained instanceof
                                        JButton){
            labelB.setText("Gained: " +
                           ((JButton)gained).
                             getActionCommand());
          }//end if
        }//end focusGained

        public void focusLost(FocusEvent e){
          labelA.setText("");
          labelB.setText("");
          Object lost = e.getSource();
          if(lost != null && lost instanceof
                                        JButton){
            labelA.setText("Lost: " +
                           ((JButton)lost).
                             getActionCommand());
          }//end if

          Component gained =
                        e.getOppositeComponent();
          if(gained != null && gained instanceof
                                        JButton){
            labelB.setText("Gained: " +
                           ((JButton)gained).
                             getActionCommand());
          }//end if
        }//end focusLost
      }//end new FocusListener
    );//end addFocusListener

  }//end constructor
}//end GUI

Listing 6



Copyright 2004, 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.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

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-






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel