全屏窗口不会使用KeyListener或KeyBoardFocusManager获取键盘输入

让我的KeyBoardFocusManger与我的全屏Window一起工作时遇到问题。 无论如何,它只是不会得到键盘输入。 我使用System.exit(0)println()来查找对keypressed / release / typed方法的任何调用,但不会抛出任何错误。 我试过KeyListeners ; 但在我读完之后,我改为使用KeyboardFocusManager ,同样的事情仍然发生。 我真的很绝望; 从我可以判断, Window没有得到键盘的焦点?

这是我的主要内容:

 public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { // Determine if full-screen mode is supported directly GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); if (gs.isFullScreenSupported()) { Frame frame = new Frame(gs.getDefaultConfiguration()); SpaceInvaderUI spaceInvaderUI = new SpaceInvaderUI(frame); // Enter full-screen mode gs.setFullScreenWindow(spaceInvaderUI); } else { JOptionPane.showMessageDialog(null, "Does not support full screen!", "Error 0x01", JOptionPane.ERROR_MESSAGE); System.exit(1); } } }); } 

这里是包含KeyBoardFocusManger的UI,并添加到addListeners()方法中:

 class SpaceInvaderUI extends Window { private JPanel drawingPanel; private Image background; private JButton btnExit; public SpaceInvaderUI(Frame frame) { super(frame); try { background = ImageIO.read(getClass().getResourceAsStream("background.png")); } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Could not extract resource: " + ex.getMessage(), "Error 0x02", JOptionPane.ERROR_MESSAGE); System.exit(2); } createWindow(); } private void createComponents() throws HeadlessException { drawingPanel = new DrawingPanel(background, this); btnExit = new JButton("Exit"); } private void createWindow() { createComponents(); addListeners(); addComponentsToWindow(); } private void addComponentsToWindow() { add(drawingPanel, BorderLayout.CENTER); add(btnExit, BorderLayout.SOUTH); } private void addListeners() { KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.addKeyEventDispatcher(new MyDispatcher()); btnExit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.exit(0); } }); } private class MyDispatcher implements KeyEventDispatcher { @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED) { System.out.println("pressed"); System.exit(0); } else if (e.getID() == KeyEvent.KEY_RELEASED) { System.out.println("released"); System.exit(0); } else if (e.getID() == KeyEvent.KEY_TYPED) { System.out.println("Typed"); System.exit(0); } return false; } } } 

退出按钮只是因为我厌倦了通过taskmanager杀死我的应用程序。 最后,这是我的小组,游戏将在其上进行,我的背景将被绘制:

 public class DrawingPanel extends JPanel { private final Image background; private final SpaceInvaderUI invaderUI; DrawingPanel(Image background, SpaceInvaderUI invaderUI) { this.background = background; this.invaderUI = invaderUI; } @Override protected void paintComponent(Graphics grphcs) { super.paintComponent(grphcs); grphcs.drawImage(background.getScaledInstance((int) invaderUI.getWidth(), (int) invaderUI.getHeight(), Image.SCALE_SMOOTH), 0, 0, this); } } 

先谢谢你。

编辑:我现在尝试在我的drawingPanel上使用键绑定但是当我按下f2时仍然没有任何反应:

 class SpaceInvaderUI extends Window { private JPanel drawingPanel; private Image background; private JButton btnExit; public SpaceInvaderUI(Frame frame) { super(frame); try { background = ImageIO.read(getClass().getResourceAsStream("background.png")); } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Could not extract resource: " + ex.getMessage(), "Error 0x02", JOptionPane.ERROR_MESSAGE); System.exit(2); } createWindow(); } private void createComponents() throws HeadlessException { drawingPanel = new DrawingPanel(background, this); btnExit = new JButton("Exit"); } private void createWindow() { createComponents(); addListeners(); addComponentsToWindow(); } private void addComponentsToWindow() { add(drawingPanel, BorderLayout.CENTER); add(btnExit, BorderLayout.SOUTH); } private void addListeners() { Action exit = new AbstractAction() { public void actionPerformed(ActionEvent e) { System.exit(0); } }; drawingPanel.getInputMap().put(KeyStroke.getKeyStroke("F2"), exit); btnExit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.exit(0); } }); } } 

为什么在Swing GUI中使用AWT组件? 我担心(但不确定)通过这样做,你可能会失去一些Swingfunction。

如果您只是捕捉选择键选择击键来控制游戏,请考虑使用键绑定 。

编辑
不,AWT组件没有故障,但仍然可能不应该使用。

编辑2
您的顶级窗口由于某种原因没有聚焦。 继续测试代码……

编辑3
使用JFrame为我工作:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Test3 { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { GraphicsEnvironment ge = GraphicsEnvironment .getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); if (gs.isFullScreenSupported()) { SpaceInvaderUI spaceInvaderUI = new SpaceInvaderUI(gs.getDefaultConfiguration()); gs.setFullScreenWindow(spaceInvaderUI); } else { JOptionPane.showMessageDialog(null, "Does not support full screen!", "Error 0x01", JOptionPane.ERROR_MESSAGE); System.exit(1); } } }); } } // class SpaceInvaderUI extends JWindow { class SpaceInvaderUI extends JFrame { private JPanel drawingPanel; private Image background; private JButton btnExit; public SpaceInvaderUI(GraphicsConfiguration gc) { super(gc); createWindow(); addKeyBindings(); setUndecorated(true); } private void addKeyBindings() { int condition = JPanel.WHEN_IN_FOCUSED_WINDOW; InputMap inputMap = drawingPanel.getInputMap(condition ); ActionMap actionMap = drawingPanel.getActionMap(); boolean released = false; KeyStroke upArrowKeyStrokePressed = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released ); String upArrowPressed = "up arrow pressed"; inputMap.put(upArrowKeyStrokePressed , upArrowPressed); actionMap.put(upArrowPressed, new AbstractAction() { @Override public void actionPerformed(ActionEvent arg0) { System.out.println("up arrow pressed"); } }); released = true; String upArrowReleased = "up arrow released"; KeyStroke upArrowKeyStrokeReleased = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released ); inputMap.put(upArrowKeyStrokeReleased , upArrowReleased); actionMap.put(upArrowReleased , new AbstractAction() { @Override public void actionPerformed(ActionEvent arg0) { System.out.println("up arrow released"); } }); } private void createComponents() throws HeadlessException { drawingPanel = new DrawingPanel(background, this); btnExit = new JButton("Exit"); } private void createWindow() { createComponents(); addListeners(); addComponentsToWindow(); } private void addComponentsToWindow() { add(drawingPanel, BorderLayout.CENTER); add(btnExit, BorderLayout.SOUTH); } private void addListeners() { // KeyboardFocusManager manager = KeyboardFocusManager // .getCurrentKeyboardFocusManager(); // manager.addKeyEventDispatcher(new MyDispatcher()); btnExit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.exit(0); } }); } // // private class MyDispatcher implements KeyEventDispatcher { // // @Override // public boolean dispatchKeyEvent(KeyEvent e) { // System.out.println("in dispatch. KeyEvent := " + e); // if (e.getID() == KeyEvent.KEY_PRESSED) { // System.out.println("pressed"); // System.exit(0); // } else if (e.getID() == KeyEvent.KEY_RELEASED) { // System.out.println("released"); // System.exit(0); // } else if (e.getID() == KeyEvent.KEY_TYPED) { // System.out.println("Typed"); // System.exit(0); // } // return false; // } // } } class DrawingPanel extends JPanel { private final Image background; private final SpaceInvaderUI invaderUI; DrawingPanel(Image background, SpaceInvaderUI invaderUI) { this.background = background; this.invaderUI = invaderUI; setBackground(Color.pink); } @Override protected void paintComponent(Graphics grphcs) { super.paintComponent(grphcs); } } 

如此相关的FullScreenTest所示,您可以对按钮键绑定使用相同的Action实例。

附录:@nIcE cOw问: 我们可以 使用 InputMap ActionMap 在同一个 JComponent 上添加多个键并使用相同的 AbstractAction 吗?

是的,可以使用多个键绑定; 我有时会调用doClick()来获取视听反馈,如下所示。