java - 为什么当我按下 JFrame 时,焦点永远不会从我的组件中丢失?

标签 java swing focus jframe focuslistener

我对 CustomTextField 类实现的焦点监听器有问题。仅当另一个 Swing 组件获得焦点时才会调用焦点监听器。但是,如果我通过用鼠标拖动 JFrame istelf 来移动它,则永远不会调用 focusLost() 方法(换句话说,焦点似乎没有从 CustomTextField 转移到 JFrame)。

编辑:我的问题的解决方案如下:

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;

public class ScrollFocus extends JFrame {

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new ScrollFocus();
        }
    });
}

public ScrollFocus() {
    this.setLayout(new BorderLayout());
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Vector<String> values = new Vector<>();
    values.add("a");
    values.add("b");
    values.add("c");
    values.add("d");
    values.add("e");
    JComboBox<String> comboBox = new JComboBox<>(values);
    JScrollPane scrollPane = new JScrollPane(comboBox);
    this.add(scrollPane, BorderLayout.NORTH);

    CustomTextField customTextField = new CustomTextField();
    this.add(customTextField, BorderLayout.CENTER);

    JButton button = new JButton("press");
    final JPopupMenu menu = new JPopupMenu("Menu");
    menu.add(new JMenuItem("Test"));
    button.setComponentPopupMenu(menu);
    this.add(button, BorderLayout.SOUTH);

    pack();
    setVisible(true);
}

class CustomTextField extends JTextField implements FocusListener {

    private CustomPopup customPopup = new CustomPopup();

    public CustomTextField() {
        this.addFocusListener(this);


        this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "VK_UP");
        this.getActionMap().put("VK_UP", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                setPopupSize();
                customPopup.show(CustomTextField.this, CustomTextField.this.getX(), CustomTextField.this.getY() + CustomTextField.this.getHeight());    
                customPopup.setSelectedIndex(0);
            }
        });
        this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "VK_DOWN");
        this.getActionMap().put("VK_DOWN", new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                setPopupSize();
                customPopup.show(CustomTextField.this, CustomTextField.this.getX(), CustomTextField.this.getY() + CustomTextField.this.getHeight());
                customPopup.setSelectedIndex(0);
            }
        });
    }

    public void setPopupSize() {
        customPopup.setPopupSize(new Dimension(this.getWidth(), 110));
    }

    @Override
    public void focusGained(FocusEvent e) {
    }

    @Override
    public void focusLost(FocusEvent e) {
    }

    class CustomPopup extends JPopupMenu {
        String[] values = new String[]{"Value1", "Value2", "Value3", "Value4", "Value5", "Value6", "Value7",
                "Value8","Value9", "Value10", "Value11", "Value12", "Value13", "Value14", "Value15", "Value16",};
        JList<String> list = new JList<>(values);
        JScrollPane scrollPane = new JScrollPane(list);
        public int index = 0;

        public CustomPopup() {
            this.setLayout(new GridLayout(0,1));
            this.add(scrollPane);
            this.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if(e.getKeyCode() == KeyEvent.VK_UP){
                        if(customPopup.index > 0)
                            customPopup.setSelectedIndex(--customPopup.index);
                    }
                    else if(e.getKeyCode() == KeyEvent.VK_DOWN){
                        if(customPopup.index < customPopup.getListSize()-1)
                            customPopup.setSelectedIndex(++customPopup.index);
                    }
                }
            });
            this.addFocusListener(new FocusAdapter() {
                @Override
                public void focusLost(FocusEvent e) {
                    index=0;
                }
            });
            pack();

        }

        public void setSelectedIndex(int index) {
            list.setSelectedIndex(index);
            list.ensureIndexIsVisible(index);
            requestFocus();
        }

        public int getListSize() {
            return values.length;
        }
    }
}
}

最佳答案

//customPopup.setVisible(true);
customPopup.show((JComponent)e.getSource(), 0, 20);

您应该使用 show(...) 方法来显示弹出窗口。这必须向弹出窗口添加一些监听器,这样您就不再需要文本字段上的 FocusListener。

但是,现在这是一个不同的问题。文本字段失去焦点,因此永远不会调用操作。这没问题,但 JList 永远不会获得焦点,因此它不会响应向上/向下键,除非您先单击列表框。我不确定这里出了什么问题。

也许您可以尝试使弹出窗口、滚动 Pane 和列表全部不可聚焦,以便焦点保留在文本字段上?

关于java - 为什么当我按下 JFrame 时,焦点永远不会从我的组件中丢失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16870922/

相关文章:

interface - 有没有类似于 Callable<V> 但不抛出已检查异常的标准 JDK 接口(interface)?

java - 如何在面板中插入 ImageIcon?

javascript - 如何在 alert() 之后给予 focus()?

java - 在 JXTable 中隐藏一个列?

focus - Corona 中的对象焦点

jquery focus() for Tab 在 Asp.Net 中跳转两次

java - 在 Java 中验证 CCN?

java - 如何使用 2 个可用按钮中的一个按钮调用 FileExplorer.java?

java - 如何在 Wear OS 中将秒针 watch 在一秒钟内旋转五次?

Java API "Run on EDT if not on EDT"