JDK-4531346 : REGRESSION: InputVerifiers behavior in 1.4 not compatible with 1.3
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P1
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2001-11-26
  • Updated: 2001-11-26
  • Resolved: 2001-11-26
Related Reports
Duplicate :  
Description

Name: jl125535			Date: 11/26/2001


java version "1.4.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b84)
Java HotSpot(TM) Client VM (build 1.4.0-beta3-b84, mixed mode)

The behavior of InputVerifier in 1.4 is not fully compatible with 1.3
Both of the behaviors below were verified in Windows 2000 and Solaris 8.

A) In 1.4 the InputVerifier is executed every time a user clicks with the mouse
in the JTextField - even if the TexfField already has keyboard focus. In 1.3
this only occurs once.

B) If the shouldYieldFocus()-method of a InputVerifer shows a dialog when the
user has entered a incorrect value the application enters a closed loop.
* Showing the dialog causes the InputVerifier to execute
* This pops up the dialog
* Showing the dialog causes the InputVerifier to execute
....forever.
In 1.3 showing the dialog would not start the InputVerifier.


When running the attached code, A is exemplified just by clicking with the
mouse several times in the field with the text "No Popup". Note that the
shouldYieldFocus() executes each time. Also note that navigating to the field
by using tab does not cause the shouldYieldFocus() to execute (which is correct)

Leaving the field named "With popup" by using TAB exemplifies the closed loop
described as B. This also occurs if any other field has focus and you click
with the mouse in the field.


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

public class InputVerifierTest extends JFrame implements ActionListener {

    InputVerifierTest() {
        JDesktopPane desktop   = new JDesktopPane();
        Container contentPane = getContentPane();
        contentPane.add(desktop,BorderLayout.CENTER);
        desktop.add(createFrame("A"));
        desktop.add(createFrame("B"));
        JPanel top = new JPanel();
        top.setLayout(new BorderLayout());
        top.addFocusListener(new MyFocusListener("Top"));
    }
    
    private JInternalFrame createFrame(String name) {
        JInternalFrame internalFrame = new JInternalFrame
(name,true,true,true,true);
        internalFrame.setVisible(true);
        internalFrame.setSize(200,300);
        internalFrame.addFocusListener(new MyFocusListener("internalFrame " +
name));
        try {
            internalFrame.setSelected(true);
        } catch( java.beans.PropertyVetoException pe) {
            //HIDEME
        }
        internalFrame.getContentPane().setLayout(new BorderLayout());
        
        JPanel panel = new JPanel();
        
        internalFrame.getContentPane().add(panel,BorderLayout.CENTER);
        
        JTextField  textField = new JTextField("Without verifier",10);
        textField.addFocusListener(new MyFocusListener(name+ ":textField"));
        panel.add(textField);

        JTextField  textField1 = new JTextField("With popup");
        textField1.setInputVerifier(new MyVerifier(true));
        textField1.addFocusListener(new MyFocusListener(name+ ":textField1"));
        panel.add(textField1);
        
        JTextField  textField2 = new JTextField("No Popup");
        textField2.setInputVerifier(new MyVerifier(false));
        textField2.addFocusListener(new MyFocusListener(name+ ":textField2"));
        panel.add(textField2);
                
        panel.addFocusListener(new MyFocusListener(name+ ":panel"));
        
        internalFrame.getContentPane().add(new JLabel("java.version = " +
System.getProperty("java.version")),BorderLayout.SOUTH);
        
        JButton button = new JButton();
            
        button.setText("Save");
        button.addActionListener(this);
        button.addFocusListener(new MyFocusListener(name+ ":Save"));
        panel.add(button);
        
        return internalFrame;
    }
    
    public void actionPerformed(ActionEvent e) {
        System.out.println("'Saving'");
    }
    
    public static void main(String arg []) {
        InputVerifierTest test = new InputVerifierTest();
        
        test.setSize(500,500);
        test.setVisible(true);
    }

    class MyVerifier extends InputVerifier {
        private boolean popup = false;
        public MyVerifier(boolean popup) {
            this.popup = popup;
        }
        
        public boolean shouldYieldFocus(JComponent input) {
            boolean status ;
            
            System.out.println("shouldYieldFocus  BEGIN");
            status = verify(input);
            System.out.println("You wrote ='" + ((JTextField) input).getText()
+"'");
            
            if (status == false ) {
                if (popup) {
                    JOptionPane.showMessageDialog(null, "Only the text 'Jan' is
allowed","Error" , JOptionPane.ERROR_MESSAGE);
                }
                System.out.println("Only the text 'Jan' is allowed");
            } else {
                System.out.println("Correct");
            }
            System.out.println("shouldYieldFocus  END");
            return status ;
        }
        
        public boolean verify(JComponent input) {
            JTextField tf  = (JTextField) input;
            boolean status = "Jan".equals(tf.getText());
            System.out.println("Verify() returns  = " + status);
            return status;
        }
    }
        
    class MyFocusListener implements FocusListener {
        private String name ;
        MyFocusListener(String name) {
            this.name = name ;
        }
        public void focusGained(FocusEvent e) {
            System.out.println("Focus gained on " + name);
        }
        
        public void focusLost(FocusEvent e) {
            System.out.println("Focus lost on " + name);
        }
    }
}

Release Regression From : 1.3.1
The above release value was the last known release where this 
bug was knwon to work. Since then there has been a regression.

(Review ID: 135461) 
======================================================================

Comments
WORK AROUND public boolean shouldYieldFocus(JComponent input) { if (verify(input)) { return true; } // According to the documentation should yield focus is allowed to cause // side effects. So temporarily remove the input verifier on the text // field. input.setInputVerifier(null); System.out.println("Removed input verifier"); // Pop up the message dialog. String message = "Roll over the 'JButton1' with mouse pointer " + "after closing this dialog.\nIt sometimes behaves correctly " + "for the first time\n but repeating action brings incorrect " + "behaviour of button."; JOptionPane.showMessageDialog(null, message , "invalid value", JOptionPane.WARNING_MESSAGE); System.out.println("Showed message."); // Reinstall the input verifier. input.setInputVerifier(this); System.out.println("Reinstalled input verifier"); // Tell whoever called us that we don't want to yeild focus. return false; } ###@###.### 2001-11-26
26-11-2001

EVALUATION This is a duplicate of 4518307. Since verify always returns false when you popup the option pane shouldYieldFocus gets called again. You need to have it return true or uninstall the input verifier temporarily. Look at the work around. ###@###.### 2001-11-26
26-11-2001