2013 年 11 月 3 日解决:
FullScreen Swing 组件无法在 Mac OS X Mountain Lion 上的 Java 7 上接收键盘输入
事实证明,我使用的是 Mac,这是一个问题,我在上面找到了答案。希望这可以帮助任何其他有同样问题的 Mac 用户。
我创建了一个需要在 JPanel 中获得焦点的游戏,但是自从我将 JFrame 全屏设置为全屏后,游戏面板 mainPanel 就无法获得焦点。本质上,我所拥有的看起来像这个 SSCCE:
package com.StackOverflow;
import java.awt.Color;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass extends JFrame
{
private JPanel panel; //private MainPanel mainPanel;
public MainClass()
{
panel = new JPanel(true); // mainPanel = new MainPanel();
// I already set these attributes in my parent class of MainPanel, MyPanel
panel.setLayout(null);
panel.setOpaque(false);
panel.setFocusable(true);
panel.setVisible(true);
setUndecorated(true);
setLocation(0, 0);
add(panel); // add(mainPanel)
pack();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
gs.setFullScreenWindow(this);
System.out.format("%-30s:%10s\n", "panel is displayable", panel.isDisplayable());
System.out.format("%-30s:%10s\n", "panel is focusable", panel.isFocusable());
System.out.format("%-30s:%10s\n", "panel is visible", panel.isVisible());
System.out.format("%-30s:%10s\n", "panel can request focus", panel.requestFocusInWindow());
// mainPanel.run();
}
public static void main(String args[])
{
new MainClass();
}
}
输出:
mainPanel is displayable : true
mainPanel is focusable : true
mainPanel is visible : true
mainPanel can request focus : false
从 Eclipse 对 Component.requestFocusInWindow() 的定义:
如果此 Component 的顶级祖先已经是获得焦点的 Window,则请求此 Component 获得输入焦点。该组件必须是可显示的、可聚焦的、可见的,并且它的所有祖先(顶级窗口除外)都必须可见,才能授予请求。将尽一切努力满足要求;但是,在某些情况下,可能无法这样做。在此组件接收到 FOCUS_GAINED 事件之前,开发人员绝不能假定此组件是焦点所有者。
具体来说,也许除此之外,我已经创建了一个 MyPanel 类,它扩展了 JPanel 并实现了 AcionListener 和 Runnable。我使用 MainPanel 扩展了该类,并将 MainPanel 对象添加到全屏 JFrame。
MainPanel 是我控制和显示具有 keylistener 的游戏的地方。在我让我的 JFrame 全屏之前,游戏运行良好,但现在的问题是它无法获得焦点,即使其中的所有内容仍在运行(敌人仍然在屏幕上追逐玩家,但玩家无法响应。)
我向父类 MyPanel 添加了一个焦点侦听器,但它从未失去或获得焦点,直到我直接使用 mainPanel.requestFocus(),但输出告诉我它获得了焦点然后立即失去它。我什至在 JFrame 上尝试了 setFocusable(false)。
当我在 JFrame 上使用 setVisible(true),然后 revalidate() 时,输出发生了变化,我被告知 mainPanel.requestFocusInWindow() 更改为 true。然后输出告诉我 mainPanel 获得焦点,失去焦点,然后再次获得焦点。然而,自始至终,我的 Mac 每次按键时都会发出哔哔声来响应。有时,requestFocusInWindow() 返回 false,但它仍然表示 mainPanel 获得、丢失,然后最终获得焦点。
在 requestFocusInWindow() 文档的第二部分中,它说:
此方法返回一个布尔值。如果返回 false,则保证请求失败。如果返回 true,则请求将成功,除非它被否决,或者在本机窗口系统授予请求之前发生异常事件,例如处置组件的对等体。同样,虽然返回值 true 表示请求可能成功,但开发人员绝不能假定此组件是焦点所有者,直到此组件接收到 FOCUS_GAINED 事件。
这部分超出了我的想象,所以即使你不能解决这个问题,如果你知道这意味着什么,那可能会让我走上正轨。
如果我找到解决方案,我将发布有关此的更新。