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