Java Swing如何让JFrame获得焦点

Java Swing如何让JFrame获得焦点,java,swing,Java,Swing,我正在开发一个JavaSwing应用程序。我希望达到这样的效果:按快捷键让应用程序窗口显示出来。再次按快捷键或单击其他使应用隐藏的位置 我用jkeymaster注册来监听全局快捷方式的事件,效果很好。 但是当用户关注其他窗口时,比如chrome,office。。。焦点窗口将是其他应用程序。然后,如果用户使用快捷方式。我的应用程序窗口仍将显示,但无法获得焦点。谁能帮我解决这个问题。这是我的代码片段 Provider provider = Provider.getCurrentProvide

我正在开发一个JavaSwing应用程序。我希望达到这样的效果:按快捷键让应用程序窗口显示出来。再次按快捷键或单击其他使应用隐藏的位置

我用jkeymaster注册来监听全局快捷方式的事件,效果很好。 但是当用户关注其他窗口时,比如chrome,office。。。焦点窗口将是其他应用程序。然后,如果用户使用快捷方式。我的应用程序窗口仍将显示,但无法获得焦点。谁能帮我解决这个问题。这是我的代码片段

    Provider provider = Provider.getCurrentProvider(true);
    // bind shortcut
    provider.register(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), x -> {
        homePage.setVisible(!homePage.isVisible());
        if(homePage.isVisible()){
            // TODO: 2020/10/1 request focus here
            homePage.requestFocusInWindow();
            homePage.requestFocus();

            KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
            focusManager.clearGlobalFocusOwner();

            log.info("hasFocus? " + homePage.hasFocus());
            log.info("isActive? " + homePage.isActive());
        }
    });
我所尝试的:

  • requestFocus和requestFocusInWindow不工作
  • 我阅读了requestFocus的源代码。上面说

  • 因此,我尝试了focusManager.clearGlobalFocusOwner(),但它仍然不起作用。

    我尝试了一个丑陋的解决方案,使用robot模拟用户单击以获得焦点。当调用click方法时,光标将消失一段时间。但它确实有效(成功地获得焦点)

    我所做的是:

    一,


  • 通常,当您希望在父容器(如
    JPanel
    JFrame
    等)中获得焦点时,您可以通过在其子容器中调用
    requestFocusInWindow()
    方法来请求焦点

    我建议您不要在
    JFrame
    中要求焦点。在其一个组件中调用
    requestFocusInWindow()

    现在就用户体验而言,我将把重点放回最后一个被重点关注的组件。为了获得
    JFrame
    的聚焦组件,我们调用
    JFrame.getFocusOwner()
    。但是,如果
    JFrame
    处于状态
    MINIMIZED
    或处于后台,因为它没有焦点,
    getFocusOwner
    返回
    null

    因此,为了在调用全局密钥侦听器之前找到最后一个被聚焦的组件,您还可以为聚焦事件注册一个全局AWT侦听器:

    Toolkit.getDefaultToolkit().addAWTEventListener(e -> {
        if (e.getID() == FocusEvent.FOCUS_LOST) {
            if (e.getSource() instanceof Component) {
                lastFocusedComponent = (Component) e.getSource();
            }
        }
    }, FocusEvent.FOCUS_EVENT_MASK);
    
    每次焦点改变时,侦听器都会被触发。因此,您可以安全地获得具有焦点的实际最后一个组件,消除了
    null
    的机会,因为它是触发事件的组件

    之后,您只需调用
    requestFocusInWindow

    provider.register(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), e -> {
        frame.setVisible(!frame.isVisible());
        if (frame.isVisible())
            SwingUtilities.invokeLater(lastFocusedComponent::requestFocusInWindow);
    });
    
    一个有效的完整示例(您可以确认焦点已恢复):


    也许
    grabFocus()
    会起作用?@camickr感谢您的建议,但JFrame没有grabFocus方法。我尝试了homePage.getRootPane().grabFocus(),但仍然无效。
    RobotTool
    是java类吗?我不熟悉它。@Abra对不起,这是我的定制工具。我刚刚更新了代码。谢谢你的建议。它确实达到了你说的结果,但这不是我想要的。我希望JFrame能够抓住焦点,因为另一个需要是“当JFrame失去焦点时,JFrame应该自动隐藏”。如果JFrame出现时无法获得焦点,则我无法监视它的focuslost事件。我认为在不同的平台上实现是不同的。你能给我一些进一步的建议吗?
    public class RobotTool {
        private static Robot robot = Singleton.get(Robot.class);
    
        public static void click(int x, int y){
    
            Point mouseInitPosition = MouseInfo.getPointerInfo().getLocation();
            int mask = InputEvent.BUTTON1_MASK;
            robot.mouseMove(x, y);
            try{
                // wait 100ms to avoid the robot action out of order
                Thread.sleep(100);
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            robot.mousePress(mask);
            robot.mouseRelease(mask);
            robot.mouseMove((int)mouseInitPosition.getX(), (int)mouseInitPosition.getY());
        }
    }
    
    Toolkit.getDefaultToolkit().addAWTEventListener(e -> {
        if (e.getID() == FocusEvent.FOCUS_LOST) {
            if (e.getSource() instanceof Component) {
                lastFocusedComponent = (Component) e.getSource();
            }
        }
    }, FocusEvent.FOCUS_EVENT_MASK);
    
    provider.register(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), e -> {
        frame.setVisible(!frame.isVisible());
        if (frame.isVisible())
            SwingUtilities.invokeLater(lastFocusedComponent::requestFocusInWindow);
    });
    
    public class FocusExample {
        private static Component lastFocusedComponent;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
    
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                JTextField leftField = new JTextField(10);
                JTextField rightField = new JTextField(10);
    
                frame.setLayout(new FlowLayout());
                frame.add(leftField);
                frame.add(rightField);
    
                Toolkit.getDefaultToolkit().addAWTEventListener(e -> {
                    if (e.getID() == FocusEvent.FOCUS_LOST) {
                        if (e.getSource() instanceof Component) {
                            lastFocusedComponent = (Component) e.getSource();
                        }
                    }
                }, FocusEvent.FOCUS_EVENT_MASK);
    
                Provider provider = Provider.getCurrentProvider(true);
    
                provider.register(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), e -> {
                    frame.setVisible(!frame.isVisible());
                    if (frame.isVisible())
                        SwingUtilities.invokeLater(lastFocusedComponent::requestFocusInWindow);
                });
    
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            });
    
        }
    }