FocusListener & JOptionPane

FocusListener & JOptionPane

这是我的简单程序的代码。 有四个文本字段。 当光标位于第一个 textField JOptionPane 时,当我按确定时 光标移动到下一个字段并再次创建 OptionPane 等等 当光标位于第四个字段并且我在 OptionPane 上单击“确定”时,光标移动到第五个字段 "f"。 当光标在字段中时,我打印字段在数组中的位置: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) {
    }
}

当没有OptionPane时,光标从第一个字段向前移动到第四个并打印:

FIRST
SECOND
THIRD
FOURTH

但是当有JOptionPane 输出是:

FIRST
SECOND
FIRST
SECOND
THIRD
SECOND
THIRD
FOURTH
THIRD
FOURTH
FOURTH

可以看到在第二场之后又回到了第一场, 第三场之后回到第二场,而不是去第四场 在第四场之后又回到了第三场。

我想知道为什么?我该如何解决这个问题

问题是每次单击 JOptionPane 上的“确定”时,焦点都会返回到显示 JOptionPane 之前最后一个活动的 JTextField,因此新的 requestFocus 事件会添加到该控件的事件队列中。实际上,当您在执行代码时第一次单击“确定”后,会触发几个对话框,您只是看不到它,因为您每次都显示相同的文本 (HELLO)。我已经更改了您的代码以使其工作。希望对您有所帮助!

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) {
    }
}