Focus on Swing -
JavaWorld - July
1998
Tutorial Details:
Focus on Swing
Focus on Swing
By: By Mark McCulley
Explore focus management with JFC's Swing components
ocus is the mechanism that determines which of the components in a window will receive keyboard input events. A focus manager looks for special keystrokes that change the focus (usually the Tab and Shift-Tab keys), and then decides which component will next get the focus. Often, you'll want to control how the focus moves between components, especially if you're designing a complex form or dialog for users to enter information.
Java has had a focus manager for AWT components since version 1.0 of the Java Development Kit (JDK), and developers have howled about its inadequacies ever since. Well, it's time to stop howling. The focus management services provided with the Java Foundation Classes (JFC) should satisfy all of your needs for controlling focus changes.
A bit of history
The only way to manage focus changes with JDK 1.0 is through a few methods in the Component class. JDK 1.0 allows components to set the focus to themselves with requestFocus and to change the focus to the next component with nextFocus . Other than getting notification of focus changes with gotFocus and lostFocus , that's pretty much all you can do.
JDK 1.1 deprecates nextFocus and replaces it with transferFocus , which provides exactly the same functionality as nextFocus . Likewise, 1.1 deprecates gotFocus and lostFocus and replaces them with the addFocusListener method to support focus change notification using the 1.1 event model.
Neither JDK 1.0 nor 1.1 provide any means for applications to override the behavior of the focus manager, or to change the algorithm used to determine focus traversal.
What's new with Swing's focus management
Swing provides some powerful new ways to manage focus changes at the component level. Here's what you can do with focus management at that level:
Set the focus to a given component
Transfer the focus to the next component in the focus-change order
Determine if a component has the focus
Disable a component from responding to focus requests
Allow the component that currently has the focus to manage the next focus change
And if this isn't enough to meet your focus control needs, Swing allows you to create and use your own custom focus manager.
Let's take a quick look at the relationship between the AWT and Swing focus managers. The following figure shows how JFC incorporates both the AWT and Swing focus managers.
AWT and Swing focus manager relationship
Note that the AWT focus manager will manage focus for Swing components because they are extended AWT components. However, the flip side is not true: The Swing focus manager will not manage focus for AWT components. The section " Mixing AWT and Swing components " explains how to handle focus management if you're mixing these two component types in an application.
Explicitly setting the focus
There are two JComponent methods that allow you to explicitly set the focus to a given component: requestFocus and grabFocus . If you've worked with AWT components, you're probably familiar with the requestFocus method. Swing overrides this Component method with an implementation that allows you to call the new setRequestFocusEnabled method. This method can enable or disable the component from getting the focus via requestFocus .
However, you can't use setRequestFocusEnabled to prevent a component from getting the focus via the focus manager. That's because the focus manager uses a new Swing method, grabFocus , to give components the focus. grabFocus works just like requestFocus , except that you can't disable it. The Swing docs say that only focus managers should use grabFocus .
Let's take a look at a bit of sample code written for components. This code will cause a component to get the focus whenever the component is under the mouse:
// add a listener for mouse enter
addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent event) {
// Request the focus (if don't already have it)
if(!hasFocus()) { requestFocus(); }
}
});
This fragment adds a mouse listener, which is implemented in an anonymous inner class based on the MouseAdapter adapter class. The mouse adapter's mouseEntered method is called whenever the mouse passes over the component. The implementation for mouseEntered calls hasFocus to see if the component already has the focus, and if it doesn't, calls requestFocus to give the component the focus. A slightly more fail-safe way to set the focus would be:
if(!hasFocus()) {
// ensure requestFocus is enabled
if(!isRequestFocusEnabled()) { setRequestFocusEnabled(true); }
requestFocus();
}
And if you're writing a focus manager, you can use grabFocus :
if(!hasFocus()) { grabFocus(); }
Transferring the focus
Like AWT 1.1, Swing provides the means for a component to transfer the focus to the next component with the transferFocus method.
public void transferFocus();
This method can be useful for implementing components that automatically advance the focus when the user has completed whatever task or purpose is served by the component (like choosing from a group of radio buttons or items in a list). transferFocus is not really useful for explicitly setting the focus -- you would have to know which component has the focus just before the component that you actually want to set the focus to.
Detecting focus changes
Swing doesn't bring any changes to the operation of AWT 1.1's focus listener implementation. I'll give a brief description of focus listeners for those readers that aren't familiar with them; if you know this stuff you may want to skip on to the next section. Focus listeners provide a means of notifying applications when components gain or lose the focus. The adapter class for focus events, FocusAdapter , has two methods: focusGained and focusLost . The addFocusListener and removeFocusListener methods add and remove focus listeners for components. Standard event-listener stuff -- nothing fancy here. Let's glance at a piece of code. The following code fragment adds a focus listener that changes the background color when a component gets the focus.
// private instance variables
private boolean bFocusIndicated = false;
private Color originalColor;
.
.
.
// add a listener for focus events
addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
if(!bFocusIndicated) {
// set background to a darker color to indicate focus
originalColor = getBackground();
setBackground(originalColor.darker());
bFocusIndicated = true;
}
}
public void focusLost(FocusEvent e) {
// restore original background color
setBackground(originalColor);
bFocusIndicated = false;
}
});
You can't always count on getting focusGained and focusLost events in matched pairs, hence the need for the bFocusIndicated variable to keep up with whether we've indicated focus on a component.
Managing focus at the component level
Up until this point, most of what I've covered is probably familiar to you if you have much experience with AWT 1.1 components. Now we'll start getting into Swing's new and improved features. Swing provides a mechanism for component-managed focus traversal. This can be a powerful alternative to writing your own focus manager and is a better solution for developing components that have their own particular behavior when it comes to gaining and losing the focus. For example, say you want to develop a text field component that won't surrender the focus until the user enters valid data. If you've tried to implement such a component in AWT 1.1 by using the focusLost notification to validate the data and then set the focus back to the text field, you've probably experienced some frustration. One obvious solution to this problem -- calling requestFocus while processing the focusLost event -- doesn't always have a predictable outcome. With Swing components, you can override the isManagingFocus method to return true and get Tab and Shift-Tab keystrokes sent to the component's key listener. This allows the component to manage focus traversal when the component has the focus. The following code implements a text field that doesn't allow the focus to traverse to the next component until valid data is entered:
class MyTextField extends JTextField {
boolean validDataEntered = false;
// Constructors
public MyTextField () {
super();
init();
}
public MyTextField (String text) {
super(text);
init();
}
// Private initialization routine to be run at construct time
private void init() {
// add a key event listener that will consume tab keys until valid data entered in field
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
// look for tab keys
if(event.getKeyCode() == KeyEvent.VK_TAB
|| event.getKeyChar() == '\t') {
// if no valid data entered in field, consume event
// so that it won't be passed on to focus manager
if(!validDataEntered) {
event.consume();
}
}
else {
// assume any key other than tab is valid data
validDataEntered = true;
}
}
});
}
// Override to inform focus manager that component is managing focus changes
public boolean isManagingFocus() { return true; }
}
In this example, any keystrokes other than Tab keystrokes are considered to be valid data. If no valid data has been entered, the text field's key listener consumes Tab keystrokes, preventing them from reaching the focus manager. Of course, if you were implementing this technique in a real application, you would want to present a message to the user and inform them as to why they are being prevented from tabbing away from the text field. One limitation to managing focus traversal at the component level is that you can't control focus changes initiated by mouse actions. In fact, you can't even do this by writing your own custom focus manager. To control focus changes initiated by mouse actions, you'll have to modify the low-level mouse handling for all of your components.
Mixin
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Focus on Swing -
JavaWorld - July
1998
View Tutorial: Focus on Swing -
JavaWorld - July
1998
Related
Tutorials:
Java Tip 72: Press
Escape to close your Swing dialog windows
Java Tip 72: Press
Escape to close your Swing dialog windows |
Will Big Blue
eclipse the Java
tools market?
Will Big Blue
eclipse the Java
tools market? |
Take command of your
software
Take command of your
software |
A first look at JavaServer Faces, Part
2
A first look at JavaServer Faces, Part
2 |
JXMLAppKit 2.0
JXMLAppKit is a pure Swing java framework for editing an XML document with multiple XML editors. |
Hermes JMS Browser
Hermes JMS Browser
Hermes is a Swing application that allows you to interact with JMS providers.
|
Welcome to the Tonic Look & Feel.
Welcome to the Tonic Look & Feel. This pluggable look and feel is a free substitute for the default native look and feel of Swing, 'Metal', distributed under the GNU Lesser General Public License. |
Quaqua Look And Feel
Quaqua Look And Feel
The Quaqua Look and Feel (Quaqua) is an implementation of Apple's Aqua Human Interface Guidelines in Java.
Quaqua is not yet a self-contained look and feel. As Quaqua matures, it provides a steadily growing number of user elements |
Wi.Ser (WidgetServer) unified rich client framework
Wi.Ser is a Java/XML server-side GUI-framework which enables an application to run as either a monolithic Swing application, a thin-client/server Swing application, or as a Web application without any change!
|
InfoNode (Java Components)
InfoNode Docking Windows is a pure Java Swing based docking windows framework. The best way to see features of InfoNode Docking Windows is to try the Web Start demos.
|
Building Highly Scalable Servers with Java NIO
Building Highly Scalable Servers with Java NIO
I/O Event Handling
The I/O architecture of our router was strongly inspired by the Swing event-dispatch model. In Swing, events generated by the user interface are received by the JVM and stored in an even |
Ease Swing development with the TableModel Free framework
This article introduces the TableModel Free (TMF) framework which eliminates the need to use TableModels with Swing JTables. The TMF framework allows for more configurable JTables by moving all of table-specific data outside of the compiled code and into |
JXMLPad 3.1 FC
JXMLPad is a pure Swing java component/framework for editing XML/XHTML document. |
Java Resources
There are all Java freebies. Some of these are old, and not under maintenance. Download and use them at your risk. In case of queries, mail subrahmanyam_avb@technologist.com or varalakshmi_a@techie.com. |
JSP templates. Use JSP templates to encapsulate Webpage layout and encourage modular design
Window toolkits typically provide a layout mechanism that positions widgets in a container. For example, AWT and Swing have layout managers, and VisualWorks Smalltalk has wrappers. This article presents a template mechanism for JSP that allows layout to b |
What's New in Swing?
A new skinnable look and feel (Synth), printing support for |JTable| components, the ability to add components directly to a frame, these are a few of the new features in Swing for J2SE 5.0. |
Open Source Web Frameworks in Java
Open Source Web Frameworks in Java
Open Source Web Frameworks in Java
Struts
Struts Frame work is the implementation of Model-View-Controller (MVC) design pattern for the JSP. Struts is maintained as a part of Apache Jakarta project and is open |
Enhance your end-user MDI experience with JExplose
Enhance your end-user MDI experience with *JExplose* ! Extremely simple to integrate with your existing Swing MDI products. |
Sanssouci is a Java framework for autogenerating fancy Swing-GUIs via introspection.
Sanssouci is a Java framework for autogenerating fancy Swing-GUIs via introspection which display objects directly to the user |
J2SE Platform Migration Guide (pdf)
This guide helps developers migrate Java applets, standalone applications, Java Web Start applications and development tools from version 1.3 and 1.4 of the Java platform to version 5.0. |
|
|
|