簡體   English   中英

Java Swing 如何讓 JFrame 獲得焦點

[英]Java Swing how to let the JFrame gain focus

我正在開發一個 java swing 應用程序。 我希望達到這樣的結果:按快捷方式讓應用程序窗口出現。 再次按快捷方式或單擊其他位置讓應用程序隱藏。

我用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());
        }
    });

我嘗試過的:

  1. requestFocus 和 requestFocusInWindow,不起作用
  2. 我閱讀了 requestFocus 的源代碼。 它說
     * This method cannot be used to set the focus owner to no Component at
     * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code>
     * instead.

所以我嘗試了 focusManager.clearGlobalFocusOwner() 但它仍然不起作用。

通常,當您想在父容器(例如JPanelJFrame等)中獲得焦點時,您可以通過將requestFocusInWindow()方法調用到其子容器之一來請求焦點。

我建議你不要在JFrame要求焦點。 在其組件之一中調用requestFocusInWindow()

現在就 UX 而言,我會將重點放回到上一個重點關注的組件上。 為了獲得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);
});

一個有效的完整示例(您可以確認自己已恢復焦點):

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

    }
}

我嘗試了一個丑陋的解決方案,使用機器人來模擬用戶點擊以獲得焦點。 當調用 click 方法時,光標會消失一會兒。 但它確實有效(成功獲得焦點)

我所做的是:

1.

RobotTool.click((int)windowLocation.getX(), (int)windowLocation.getY());
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());
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM