文本字段失去对其他窗口的焦点



在java-swing应用程序中,我有一个带有某种帮助弹出窗口的文本字段。
即,当用户在文本字段中双击鼠标时,将显示此弹出窗口(实现为未修饰的 JFrame(。

一旦文本字段失去焦点,此弹出窗口就会再次隐藏。
问题在于,显示此弹出窗口时,焦点会自动移动到该帧,从而在文本字段上触发 lostFocus 事件。当然,这会再次关闭弹出窗口。

我希望仅当文本字段失去对同一窗口中另一个组件的焦点时,才会触发 lostFocus 事件。

知道如何做到这一点吗?

解决方案比我想象的要容易:
focusLost回调中,检查isTemporary()标志。
如果设置,请忽略该事件。

更新:
如果设置了 ifTemporary() 标志,请确定获得焦点的组件(通过 getOppositeComponent() (。
如果该组件null,或其父窗口不是我们的弹出框架,则无论如何都要关闭弹出窗口。

检查哪个对象已收到焦点,并根据它隐藏窗口。

这是一个粗略的例子

public class MainFrame extends JFrame {
    private JWindow popupWindow;
    public MainFrame() throws HeadlessException {
        super("Main Frame");
        createGUI();
    }
    private void createGUI() {
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setPreferredSize(new Dimension(600, 400));
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        JTextField hintTextField = new JTextField();
        popupWindow = new JWindow(this);
        popupWindow.getRootPane().setBorder(BorderFactory.createLineBorder(Color.RED));
        popupWindow.getRootPane().setLayout(new BorderLayout());
        popupWindow.getRootPane().add(hintTextField, BorderLayout.CENTER);
        for(int i = 0; i < 10; i++) {
            JTextField textField = new JTextField();
            textField.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if(e.getClickCount() == 2) {
                        Point point = textField.getLocationOnScreen();
                        popupWindow.setBounds(point.x, point.y + textField.getPreferredSize().height, 200, 200);
                        popupWindow.setVisible(true);
                    }
                }
            });
            textField.addFocusListener(new FocusAdapter() {
                @Override
                public void focusLost(FocusEvent e) {
                    if(e.getOppositeComponent() != hintTextField) {
                        popupWindow.setVisible(false);
                    }
                }
            });
            panel.add(textField);
        }
        add(panel, BorderLayout.PAGE_START);
        pack();
        setLocationRelativeTo(null);
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
    }
}

最新更新