javaswingjoptionpanefocuslistener

FocusListener & JOptionPane


There is the code of my simple Program. There are four textFields. when cursor is on first textField JOptionPane is Created and when I press ok cursor moves to next field and OptionPane is created again and so on when cursor is on fourth field and I click OK on OptionPane,cursor moves to fifth field "f". when cursor is in field,I print the possition of the field in array: System.out.println("first or Second or Third or Fourth")

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Hello extends JFrame implements ActionListener, FocusListener {

    public JTextField[] fields = new JTextField[4];
    public JPanel panel = new JPanel();
    public JTextField f = new JTextField(12);
    public static void main(String[] args) {
        new Hello();
    }

    public Hello() {
        for (int i = 0; i < 4; i++) {
            fields[i] = new JTextField(12);
            fields[i].addFocusListener(this);
            panel.add(fields[i]);
        }
        add(panel);
        add(f);
        setTitle("Hello World");
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(920, 420);
        setLocation(100, 100);
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
    }

    @Override
    public void focusGained(FocusEvent fe) {
        if (fe.getSource() == fields[0]) {
             JOptionPane.showMessageDialog(null, "HELLO");             
            fields[1].requestFocus();
            System.out.println("FIRST");
        } else if (fe.getSource() == fields[1]) {
             JOptionPane.showMessageDialog(null, "HELLO");           
            fields[2].requestFocus();
            System.out.println("SECOND");
        } else if (fe.getSource() == fields[2]) {
             JOptionPane.showMessageDialog(null, "HELLO");            
            fields[3].requestFocus();
            System.out.println("THIRD");
        } else if (fe.getSource() == fields[3]) {
             JOptionPane.showMessageDialog(null, "HELLO");          
              f.requestFocus();
                System.out.println("FOURTH")
        }
    }

    @Override
    public void focusLost(FocusEvent fe) {
    }
}

When there is no OptionPane,the cursor moves forward from first field to the fourth and prints:

FIRST
SECOND
THIRD
FOURTH

but when there is JOptionPane the output is :

FIRST
SECOND
FIRST
SECOND
THIRD
SECOND
THIRD
FOURTH
THIRD
FOURTH
FOURTH

One can see that after second field it comes back to first, after third field it comes back to second,instead of to go to fourth after fourth field it comes back to third.

I want to know why? and how can I fix this


Solution

  • The problem is that every time you click OK on the JOptionPane, the focus is returned to the last JTextField active before the JOptionPane was shown, so a new requestFocus event is added to the event queue for that control. Actually after the first time you click OK while executing your code, several dialogs are fire, you just don't see it because you show the same text (HELLO) every time. I have changed your code to make it work. Hope it helps!

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.util.ArrayList;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    
    public class testOptionPane extends JFrame implements ActionListener, FocusListener {
    
        public ArrayList<JTextField> fields = new ArrayList<>();
        public JPanel panel = new JPanel();
        public JTextField f = new JTextField(12);
        private int currentField = 0;
        private boolean focusReturned = false;
        public static void main(String[] args) {
            new testOptionPane();
        }
    
        public testOptionPane() {
            for (int i = 0; i < 4; i++) {
                JTextField tf = new JTextField(12);
                fields.add(tf);
                tf.addFocusListener(this);
                panel.add(tf);
            }
            add(panel);
            fields.add(f);
            add(f);
            setTitle("Hello World");
            getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(920, 420);
            setLocation(100, 100);
            setVisible(true);
        }
    
        @Override
        public void actionPerformed(ActionEvent ae) {
        }
    
        @Override
        public void focusGained(FocusEvent fe) {
            if (fe.getSource() == fields.get(currentField)) {
                if (!focusReturned) {
                    JOptionPane.showMessageDialog(this, "focus on field " + String.valueOf(currentField));
                    System.out.println(currentField);
                    focusReturned = true;
                } else {
                    currentField++;
                    focusReturned = false;
                    if (currentField < fields.size()) {
                        fields.get(currentField).requestFocus();
                    }
                }
            }
        }
    
        @Override
        public void focusLost(FocusEvent fe) {
        }
    }