[英]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());
}
});
我嘗試過的:
* This method cannot be used to set the focus owner to no Component at
* all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code>
* instead.
所以我嘗試了 focusManager.clearGlobalFocusOwner() 但它仍然不起作用。
通常,當您想在父容器(例如JPanel
、 JFrame
等)中獲得焦點時,您可以通過將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.