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
When initially learning an API, a programmer rapidly forms a conceptual model of the implementation behind the interface. Unfortunately, programmers' preliminary models often represent the shortest distance from problem domain to solution. When the underlying implementation differs from your simple conceptual model, a trap awaits you.

In this article, you will examine two simple traps that many programmers stumble upon the first time they work with APIs. Hidden complexities in the implementation often muddy a simple conceptual model, thereby causing a trap. This month, you will uncover two examples of the model-implementation mismatch: the first when creating a Swing GUI and the second when finding a specific node in a Document Object Model (DOM).

Pitfall 7: When requestFocus() fails

You can validate a form's text field in several different ways. One approach is to validate the text field after the component has lost cursor focus. You accomplish that by registering a FocusListener with the component and checking the field value in the focusLost() method, as Listing 7.1, BadRequestFocus.java, demonstrates:

(Note: You can download all the source code that accompanies this article from Resources.)

Listing 7.1: BadRequestFocus.java

package com.javaworld.jpitfalls.article4;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class BadRequestFocus extends JFrame implements FocusListener
{
   public static final String NAME = "Name";
   public static final String AGE = "Age";
   public static final String BIRTHDAY = "Birthday";
   
   JTextField nameTF = new JTextField(20);
   JTextField ageTF = new JTextField(5);
   JTextField birthdayTF = new JTextField(12);
   JTextField status = new JTextField(40);
   HashMap map = new HashMap();
   
   public BadRequestFocus()
   {
      getContentPane().setLayout(new BorderLayout(2,2));
      Panel northP = new Panel(new FlowLayout(FlowLayout.CENTER));
      Panel centerP = new Panel(new GridLayout(3,1));
      Panel southP = new Panel(new FlowLayout(FlowLayout.LEFT));
      getContentPane().add("North", northP);
      getContentPane().add("Center", centerP);
      getContentPane().add("South", southP);
      
      // set up North Panel
      northP.add(new JLabel("Request Focus Tester"));
         
      // set up Center Panel
      Panel p1 = new Panel(new FlowLayout(FlowLayout.LEFT));
      p1.add(new JLabel(NAME));
      p1.add(nameTF);
      centerP.add(p1);
      Panel p2 = new Panel(new FlowLayout(FlowLayout.LEFT));
      p2.add(new JLabel(AGE));
      p2.add(ageTF);
      centerP.add(p2);
      Panel p3 = new Panel(new FlowLayout(FlowLayout.LEFT));      
      p3.add(new JLabel(BIRTHDAY));
      p3.add(birthdayTF);
      centerP.add(p3);
      
      // set up the South Panel
      status.setEditable(false);
      status.setText("Ready.");
      southP.add(status);
      
      // Frame only
      addWindowListener(new WindowAdapter()
                    {
                     public void windowClosing(WindowEvent wevt)
                     {
                        System.exit(0);   
                     }
                    });
                    
      // add this class as a FocusListener to the TextFields
      nameTF.addFocusListener(this);
      nameTF.setRequestFocusEnabled(true);
      ageTF.addFocusListener(this);
      ageTF.setRequestFocusEnabled(true);
      birthdayTF.addFocusListener(this);      
      birthdayTF.setRequestFocusEnabled(true);
      // map the components to a field name for validation
      map.put(nameTF, NAME);
      map.put(ageTF, AGE);
      map.put(birthdayTF, BIRTHDAY);
                          
      // show the window              
      setLocation(100,100);
      pack();
      setVisible(true);
   }
   
   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("");
                  // get the focus back to try again
                  tf.requestFocus(); 
                  status.setText("Failed Field Validation. 
Re-enter.");                  
                 }
            }            
            else if (fieldName.equals(BIRTHDAY))
            {
               // validate the date...   
            }
         }
         else
            status.setText("Unable to Validate. Unknown field");
      }
   }   
   
   public static void main(String args[])
   {
      try
      {
         new BadRequestFocus();      
      } catch (Throwable t)
        {
         t.printStackTrace();
        }
   }
}


When Listing 7.1 executes, the program displays the GUI shown below:

  • Print
  • Feedback

Resources