Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

An API's looks can be deceiving

Penetrate the hidden complexities that spoil simple conceptual models of Java APIs

  • Print
  • Feedback

Page 2 of 4

Request focus tester



While most of the code (the BadRequestFocus constructor) creates the user interface (UI), the pitfall lies in the focusLost() method, which tries to request focus inside the focus notification.

In focusLost(), you first retrieve the field name associated with the JTextField so you know how to validate the field. That is done via the map HashMap. In the example above, I validate only the age field and validate that the value entered in the field is an integer. If the validation fails, I set the text field to an empty string and call requestFocus() to return the cursor to the component I am validating. Unfortunately, due to the complexity of event handling in a Swing UI, requestFocus() does not in fact obtain the focus when called inside the lostFocus() method.

You cannot request an event at any time without regard to the current states of both the Swing interface and the event-dispatcher thread. Luckily, we don't need to examine the Swing implementation source code to find a solution to this problem; Swing provides a utility method called invokeLater() that executes code on the event-dispatching thread at a later time. In our case, making use of this method properly invokes the requestFocus() method. Listing 7.2, GoodRequestFocus.java, uses that approach:

Listing 7.2: GoodRequestFocus.java

package com.javaworld.jpitfalls.article4;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
  
class FocusRequester implements Runnable
{  
   private Component comp;
  
   public FocusRequester(Component comp)
   {
      this.comp = comp;
      try 
      {
         SwingUtilities.invokeLater(this);
      } catch(Exception e) 
        {
         e.printStackTrace();
        }
   }
   
   public void run()
   {
      comp.requestFocus();
   }
}
public class GoodRequestFocus extends JFrame implements FocusListener
{
   // data members identical to BadRequestFocus class ...
   public GoodRequestFocus()
   {
        // this code identical to BadRequestFocus() ...
   }
   
   public void focusGained(FocusEvent fevt)
   {
      System.out.println("Focus Gained.");      
   }
   
   public void focusLost(FocusEvent fevt)
   {
      Component c = fevt.getComponent();
      if (c instanceof JTextField)
      {
         JTextField tf = (JTextField) c;
         String val = tf.getText();
         // get the field name         
         String fieldName = (String) map.get(tf);
         if (fieldName != null)
         {
            if (fieldName.equals(AGE))
            {
               try
               {
                  int i = Integer.parseInt(val);
                  status.setText("Age is Valid.");
               } catch (NumberFormatException nfe)
                 {
                  // FAILED VALIDATION
                  // empty field
                  tf.setText("");
                  status.setText("Failed Field Validation. 
Re-enter.");
                  // get the focus back to try again
                  new FocusRequester(c); 
                 }
            }            
            else if (fieldName.equals(BIRTHDAY))
            {
               // validate the date...   
            }
         }
         else
            status.setText("Unable to Validate. Unknown field");
      }
   }   
   
   public static void main(String args[])
   {
      try
      {
         new GoodRequestFocus();      
      } catch (Throwable t)
        {
         t.printStackTrace();
        }
   }
}


The key that makes the focus request work is the added FocusRequester class, which invokes SwingUtilities.invokeLater(). The FocusRequester class implements Runnable and thus has a run() method that calls requestFocus() on the Component passed in to its constructor.

  • Print
  • Feedback

Resources