Java LostFocus 和 InputVerifier,按反向制表符顺序移动

2024-05-14

我有一个 GUI 应用程序,它使用 InputVerifier 在产生焦点之前检查文本字段的内容。这都是很正常的。然而,昨天发现了一个问题——这似乎是一个错误,但我在任何地方都找不到任何提及它的地方。在我将其报告为错误之前,我想我应该问:我在这里遗漏了一些明显的东西吗?

情况:

  • 一组带有输入验证器的文本字段。
  • 所有控件上的 FocusLost 和 FocusGained 监听器,这样我就可以看到发生了什么。
  • 一个单独的线程使用 DefaultKeyboardFocusManager 报告(每 2 秒)哪个控件具有焦点。
  • 我将无效数据放置在表单中间的 JTextField 中,并尝试离开控件。

如果我尝试使用鼠标或 Tab 键离开此控件,我做不到。 FocusLost 事件不会触发,控件会正确保留焦点。

但是,如果我尝试使用 Shift-Tab 以相反的 Tab 键顺序离开控件,有时FocusLost 事件触发。如果发生这种情况,单独的线程会报告没有控件获得焦点,即 getFocusOwner() 返回 null。


Edit: below is a small sample program that shows the problem. The problem has nothing to do with the extra thread - the thread is just there to make the problem more obvious. If there is a race-condition, it is somewhere in Swing.

要查看问题,请转到第二个文本框并将其清空。控件应保留焦点,并且确实如此unless您可以通过按 Shift-Tab 键将其保留。与完整的应用程序不同,该错误似乎 100% 的时间都会发生。在 OpenJDK 6 和 Oracle Java 7 下都是如此。

这几乎太明显了,不可能是一个错误,而且它发生在多个 Java 环境中。因此,我怀疑我遗漏了一些明显的东西。任何人?

public class FocusBugDemo extends JFrame {
    static JTextField txtOne = new JTextField("Ignore this control");
    static JTextField txtTwo = new JTextField("Delete this text, then press shift-tab");
    static JLabel lblFocus = new JLabel("");
    static KeyboardFocusManager kfm = new DefaultKeyboardFocusManager();

    public static void main(String[] args) {
        new FocusBugDemo();
        Thread t = new Thread() {
            @Override
            public void run() {
                while(true) {
                    Component c = kfm.getFocusOwner();
                    String focusInfo = "elsewhere";
                    if (c == null) {                        focusInfo = "null";
                    } else if (c == txtOne) {       focusInfo = "txtOne";
                    } else if (c == txtTwo) {       focusInfo = "txtTwo";
                    }
                    lblFocus.setText(System.currentTimeMillis() + " - Focus owner " + focusInfo);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                }
            }
        };
        t.start();
    }

    private FocusBugDemo() {
        super("Focus bug demo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(300,100));
        setLayout(new GridLayout(3,1));
        NotEmpty validator = new NotEmpty();
        txtOne.setInputVerifier(validator);
        txtTwo.setInputVerifier(validator);
        add(txtOne);
        add(txtTwo);
        add(lblFocus);
        pack();
        setVisible(true);
    }

    private class NotEmpty extends InputVerifier {
        @Override
        public boolean verify(JComponent input) {
            JTextField txtField = (JTextField) input;
            return (txtField.getText().length() > 0);
        }
    }
}

现在作为错误报告给 Oracle7167871 https://bugs.java.com/bugdatabase/view_bug?bug_id=7167871.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java LostFocus 和 InputVerifier,按反向制表符顺序移动 的相关文章

随机推荐