2012-06-24 19 views
7

我在使我的KeyBoardFocusManger與我的全屏Window一起工作時出現問題。無論如何,它只是不會得到鍵盤輸入。我使用了System.exit(0)println()來查找對按鍵/釋放/類型方法的任何調用,但不會引發錯誤。我試過KeyListeners;但是當我讀到this後,我改爲KeyboardFocusManager,同樣的事情仍然發生。我真的很絕望;從我可以判斷,Window沒有得到鍵盤的焦點?全屏窗口無法使用KeyListener或KeyBoardFocusManager獲取鍵盤輸入

這裏是我的主:

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

它不是一個框架,但一個窗口,我可以用一個按鈕來關閉它,但我想在遊戲中使用的「ESC」鍵退出並彈出菜單等 –

+0

然後我猜鍵聯結正是能爲工作您。 –

回答

5

你爲什麼要使用AWT組件的Swing GUI的?我擔心(但不知道),通過這樣做,你可能會失去一些Swing功能。

如果您只是捕捉選擇鍵選擇擊鍵來控制遊戲,請考慮使用Key Bindings

編輯
沒有,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); 
    } 
} 
+0

aaaahhh我是多麼愚蠢,我專注於在'Window'中添加鍵綁定,這顯然是不可能的,從來沒有想過把它添加到我的面板。非常感謝:) –

+0

我試過了,但它不起作用,什麼都沒有發生? –

+0

@DavidKroukamp:看到編輯3. –

4

如該相關FullScreenTest所示,您可以使用相同的Action實例按鈕的鍵綁定。

附錄:@nIcE牛問,我們可以通過使用InputMapActionMap添加在同一JComponent多個鍵,並使用相同AbstractAction

是,多鍵綁定是可能的;我有時會調用doClick()來獲得視聽反饋,如here所示。

+0

我可以問關於KeyBinding的問題嗎?我們可以使用'InputMap'和'ActionMap'在同一個'JComponent'上添加多個鍵,並使用相同的'AbstractAction'類? –

+0

謝謝你,這似乎是我唯一的選擇,如果我不能讓我的版本工作 –