JDK-4342333 : InputVerifier should not allow events to be passed to component requesting focus
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-05-31
  • Updated: 2000-10-06
  • Resolved: 2000-10-06
Related Reports
Relates :  
Description

Name: stC104175			Date: 05/31/2000


(see also 4286708)

java version "1.3.0rc1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc1-T)
Java HotSpot(TM) Client VM (build 1.3.0rc1-S, mixed mode)

Research
The code matches the documentation in the fact that _focus_ is not transferred
to another swing component that requests it when shouldYieldFocus() returns
false.

Testing
However, during my testing, I have found that even though shouldYieldFocus()
returns false, the _actionPerformed()_ event (or valueChanged() event or
propertyChanged() event, depending on Swing component requesting focus) is sent
to the swing component requesting focus!

This event handler has no idea about the invalid entry.

Example:
In the windows explorer, rename a file (without hitting enter) and place a
vertical bar (or any illegal filename char) in the file name. (If you don't have
a windows box, please forgive me --- perhaps your SUN box has a similar file
manager application.) Now click any other tree item in the tree control on the
left hand side in order to change the folder selection. The windows explorer
displays and error message that says you've entered an invalid file name. The
tree item selection has not changed.

Observation
If the windows explorer were written in kestrel using the new InputVerifier
class, the tree selection would change while keeping focus in the component
containing invalid file name with the vertical bar.

Conclusion
The tree selection event would result in the "explorer written in swing" app
hiding the component containing the invalid file name and displaying a component
listing files associated with the folder selected in the tree control!

Question
How can I prevent the actionPerformed event (or valueChanged() event or
propertyChanged() event, depending on Swing component requesting focus) from
being sent to a Swing component when the component containing input focus
contains invalid data?

------code below-------
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import javax.swing.event.*;
 
 // This program demonstrates the use of the Swing InputVerifier class.
 // It creates two text fields; the first of the text fields expects the
 // string "pass" as input, and will allow focus to advance out of it
 // only after that string is typed in by the user.

public class VerifierTest extends JFrame
{
  JTextField jTextField1 = new JTextField();
  JTextField jTextField2 = new JTextField();
  JTree jTree1 = new JTree();

 public VerifierTest ()
 {
   addWindowListener (new MyWAdapter ());

    try
    {
      jbInit();
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
 }

  public static void main (String [] args)
  {
    Frame f = new VerifierTest ();
    f.pack();
    f.show();
  }

  class MyWAdapter extends WindowAdapter
  {
    public void windowClosing(WindowEvent event)
    {
      System.exit (0);
    }
  }

  class PassVerifier extends InputVerifier
  {
    public boolean verify(JComponent input)
    {
      JTextField tf = (JTextField) input;
      String pass = tf.getText();

      boolean bRet = false;

      if (pass.equals("pass"))
         bRet = true;

System.out.println("#verify <" + pass + ">, boolean = " + bRet );

      return bRet;
    }

    public boolean shouldYieldFocus(JComponent input)
    {
      JTextField tf = (JTextField) input;
      String pass = tf.getText();
      boolean bRet = false;

      if (pass.equals("pass"))
         bRet = true;

System.out.println("#shouldYieldFocus <" + pass + ">, boolean = " + bRet );

      return bRet;
    }
  }

  private void jbInit() throws Exception
  {
    jTextField1.setText("jTextField1");
    jTextField2.setText("jTextField2");

    jTextField1.addFocusListener(new java.awt.event.FocusAdapter()
    {
      public void focusGained(FocusEvent e)
      {
        jTextField1_focusGained(e);
      }
    });

    jTextField2.addFocusListener(new java.awt.event.FocusAdapter()
    {
      public void focusGained(FocusEvent e)
      {
        jTextField2_focusGained(e);
      }
    });

    jTree1.addTreeSelectionListener(new
javax.swing.event.TreeSelectionListener() {

      public void valueChanged(TreeSelectionEvent e) {
        jTree1_valueChanged(e);
      }
    });
    jTree1.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

      public void propertyChange(PropertyChangeEvent e) {
        jTree1_propertyChange(e);
      }
    });
    this.getContentPane().add(jTextField1, BorderLayout.CENTER);
    this.getContentPane().add(jTextField2, BorderLayout.SOUTH);
    this.getContentPane().add(jTree1, BorderLayout.WEST);

    jTextField1.setInputVerifier(new PassVerifier());
    jTextField2.setInputVerifier(new PassVerifier());
  }

  void jTextField1_focusGained(FocusEvent e)
  {
System.out.println("jTextField1 focusGained");
  }

  void jTextField2_focusGained(FocusEvent e)
  {
System.out.println("jTextField2 focusGained");
  }

  void jTree1_valueChanged(TreeSelectionEvent e)
  {
System.out.println("jTree1_valueChanged");
  }

  void jTree1_propertyChange(PropertyChangeEvent e)
  {
System.out.println("jTree1_propertyChange");
  }
}
(Review ID: 101342) 
======================================================================

Comments
WORK AROUND Name: stC104175 Date: 05/31/2000 Perhaps each Swing component receiving an action event or propertyChange event should obtain the component with focus and validate it manually before continuing with event handler. ======================================================================
11-06-2004

EVALUATION We have agonized over this problem for quite some time now. Especially with the new focus infrastrucutre that is being introduced in 1.4. What we have decided is that focus and selection are two different things. So that the Component will typically respond to the MouseEvent, potentially changing selection or firing events, regardless of it has focus. In fact this is the case with JButton already, it can be configured such that it won't obtain focus, but will still notify its listeners. In fact the explorer example actually illustrates this behavior, when you click on the tree the selection momentarily changes, the dialog is then brought up, and the selection reverts. scott.violet@eng 2000-10-06 Note, in the year and a half since I closed out this bug we have gotten a fair number of bugs/rfes requesting that we do in fact tie selection and focus together with the inputverifier, meaning that if an IV does not allow the focus change that the selecetion does not change, listeners aren't notified... Our current thinking is that we will fix this in the future. The rfe logged against this is 4533820, refer to it for all the details. ###@###.### 2002-01-11
11-01-2002