JDK-4331775 : the JRE starts 2EventHandlerMethods parallel
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-04-19
  • Updated: 2001-11-18
  • Resolved: 2001-11-18
Related Reports
Relates :  
Description

Name: skT45625			Date: 04/19/2000


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

I want to validate a JTextField (Number), so I put a FocusListener on it. If I
press the Dummy-Button, the focusLost-method starts running and while the
focusLost-Method is running the actionPerformed-Method starts.
This happens only sometimes, so please test it often.

Here is the code:
// @(#)EventProblem.java
// If you Insert into the first Textfield an a and then click on the Button
// first the focusLost-method starts and then (the focusLost-Methods isn't
// finished!) the actionPerformed-method starts. The behaviour happens only
sometimes.
//
// (C) 2000 PPI Financial Systems
//
// Manifest EventManifest.txt
/*
Main-Class: EventProblem
Implementation-Vendor: "PPI Financial Systems"
*/
//
// jar -cfm Event.jar EventManifest.txt EventProblem*
//


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

public class EventProblem
    extends JFrame
    implements FocusListener, ActionListener {

    //Constants
    private final static String NUMBER_LB = "Nummer: ";
    private final static String NUMBER_CB = "Nummer: ";
    private final static String TEXT_LB = "Text: ";
    private final static String DUMMY_BT = "Dummy-Button";
    private final static String DUMMY_TF = "Dummy-Textfield";

    private final static String[] CB_VALUES = {"-1","0","1", "a"};

    //Some static variables and methods for trace.
    private static int indent = 0;

    private static void traceEnter(String method) {

        for (int i = 0; i < indent; i++) {
            System.out.print(" | ");
        }
        System.out.println("> "+method);
        indent++;
    }

    private static void traceLeave(String method) {
        indent--;

        for (int i = 0; i < indent; i++) {
            System.out.print(" | ");
        }
        System.out.println("< "+method);
    }

    private static void tracePut(String txt) {
        for (int i = 0; i < indent; i++) {
            System.out.print(" | ");
        }
        System.out.println(txt);
    }


    //Variables
    /** NumberTextfield */
    private JTextField numberTF;
    final private JComboBox  numberCB;

    /** TextTextField */
    private JTextField textTF;

    /** DUMMYTextfield */
    private JTextField dummyTF;

    /** DUMMY-Button */
    private JButton dummyBT;


    //Constructor

    public EventProblem()  {
        super("2Events - JRE-Version "+ System.getProperty("java.version"));


        // Instanziieren der Komponenten
        numberTF = new JTextField(5);
        numberTF.setActionCommand(NUMBER_LB);

        numberCB = new JComboBox(CB_VALUES);
        numberCB.setActionCommand(NUMBER_CB + "CB");
        numberCB.setEditable(true);

        textTF = new JTextField(1);
        textTF.setActionCommand(TEXT_LB);
        textTF.setEditable(false);

        dummyBT = new JButton(DUMMY_BT);
        dummyBT.setActionCommand(DUMMY_BT);

        dummyTF = new JTextField(5);
        dummyTF.setActionCommand(DUMMY_TF);


        getContentPane().setLayout(new GridLayout(4,2,10,15));

        getContentPane().add(new JLabel(NUMBER_LB));
        getContentPane().add(numberTF);
        getContentPane().add(new JLabel(NUMBER_CB));
        getContentPane().add(numberCB);
        getContentPane().add(new JLabel(TEXT_LB));
        getContentPane().add(textTF);
        getContentPane().add(dummyBT);
        getContentPane().add(dummyTF);

        //Set focus-order
        numberTF.setNextFocusableComponent(numberCB);
        numberCB.setNextFocusableComponent(dummyBT);
        dummyBT.setNextFocusableComponent(dummyTF);
        dummyTF.setNextFocusableComponent(numberTF);

        dummyBT.addActionListener(this);
        numberTF.addFocusListener(this);

        this.pack();
        this.setLocation(100,100);
        this.setVisible(true);
    }

    //main-method
    public static void main(String[] args) {
        new EventProblem();
    }

    //FocusListener-Methods
    public void focusGained (FocusEvent fE) {
    }

    public void focusLost (FocusEvent fE) {
        String strVal = "";
        double doubleVal = 0;

        traceEnter("focusLost");
        tracePut("temporary = " + fE.isTemporary());
        if (!fE.isTemporary()) {
            if (fE.getSource().equals(numberTF)) {
                try {
                    String txt;

                    strVal = numberTF.getText();
                    if (!strVal.equals("")) {
                        doubleVal = Double.parseDouble(strVal);
                    }

                    if (doubleVal < 0) {
                        txt = "f-f";
                    } else if (doubleVal > 0) {
                        txt = "f+f";
                    } else {
                        txt = "f f";
                    }
                    textTF.setText(txt);

                } catch (Exception dwE) {
                    //dwE.printStackTrace();
                    JOptionPane.showMessageDialog(this,
"FocusLost:\n>"+strVal+"< is not a number!",
                        "Exception", JOptionPane.ERROR_MESSAGE);
                    SwingUtilities.invokeLater(
                        new Runnable() {
                            public void run() {
                                numberTF.requestFocus();
                                numberTF.selectAll();
                            }
                        }
                        );
                }
            }
        }

        traceLeave("focusLost");
    }

    //ActionListener-Methods
    public void actionPerformed(ActionEvent aE) {
        String strVal = "";
        double doubleVal = 0;

        traceEnter("actionPerformed");
        //tracePut(aE.getSource().toString());
        //tracePut(aE.getActionCommand());
        if (aE.getActionCommand().equals(DUMMY_BT)) {
            try {
                String txt;

                strVal = numberTF.getText();
                if (!strVal.equals("")) {
                    doubleVal = Double.parseDouble(strVal);
                }

                if (doubleVal < 0) {
                    txt = "a-a";
                } else if (doubleVal > 0) {
                    txt = "a+a";
                } else {
                    txt = "a a";
                }
                textTF.setText(txt);

            } catch (Exception dwE) {
                //dwE.printStackTrace();
                JOptionPane.showMessageDialog(this,
"ActionPerformed:\n>"+strVal+"< is not a number!",
                    "Exception", JOptionPane.ERROR_MESSAGE);
                SwingUtilities.invokeLater(
                    new Runnable() {
                        public void run() {
                            numberTF.requestFocus();
                            numberTF.selectAll();
                        }
                    }
                    );
            }
        }
        traceLeave("actionPerformed");
    }
}
(Review ID: 103890) 
======================================================================

Comments
EVALUATION The only time I can get this to happen is when the button gets into a invalid state. Since focus events are posted asychronously to the EventQueue it is possible to get the focus lost event inside of the action performed. The problem with the button is being tracked as bug 4368790. All you methods are being called on the AWT-EventQueue which is what you expect. By adding print statements to your code you can see which thread they are executed on. Thread.currentThread().getName() will get the name of the currently running thread. Closing as not a bug. ###@###.### 2001-11-17
17-11-2001