2012-06-24 11 views
7

Ho problemi con il mio KeyBoardFocusManger per funzionare con lo schermo intero Window. Non importa cosa, non si ottiene input da tastiera. Ho utilizzato uno System.exit(0) e un println() per cercare qualsiasi chiamata al metodo premuto a chiave/rilasciato/digitato, ma non vengono emessi errori. Ho provato KeyListeners; ma dopo aver letto this, ho cambiato in uno KeyboardFocusManager, e la stessa cosa succede ancora. Sto davvero diventando disperato; da quello che posso giudicare, lo Window non ottiene il fuoco della tastiera?La finestra a schermo intero non riceve l'input della tastiera utilizzando KeyListener o KeyBoardFocusManager

Qui è la mia principale:

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

e qui è l'interfaccia utente che contiene il KeyBoardFocusManger, e viene aggiunto in addListeners() metodo:

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; 
     } 
    } 
} 

Il pulsante di uscita è solo perché mi sono stancato di uccidendo la mia app tramite taskmanager. Infine ecco il mio pannello sul quale il gioco avrà luogo e il mio background è dipinto su:

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

Grazie in anticipo.

EDIT: ora ho provato ad utilizzare una combinazione di tasti sulla mia drawingPanel, ma ancora non succede nulla quando si preme 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

Non è una cornice ma una finestra, e potrei usare un pulsante per chiuderla ma voglio che il gioco usi il tasto "Esc" per uscire e richiamare il menu ecc. –

+0

Quindi suppongo che KeyBinding sia esattamente ciò che può funzionare per tu. –

risposta

5

perché stai usando componenti AWT nel vostro GUI Swing? Temo (ma non so per certo) che facendo questo, potresti perdere parte della funzionalità Swing.

Se si acquisisce solo la chiave di selezione, selezionare i tratti chiave per controllare il gioco, considerare l'utilizzo di Key Bindings.

Edit:
No, i componenti AWT non sono in colpa, ma ancora probabilmente non dovrebbe essere usato.

Edit 2:
tua finestra di livello superiore non è focalizzato per qualche motivo. Continuando a testare il codice ...

Edit 3:
Utilizzo di un JFrame ha lavorato per me:

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 Quanto sono stato stupido da parte mia, ero concentrato sull'aggiunta di keybindings alla 'Window', che ovviamente è impossibile, non ho mai pensato di aggiungerlo al mio pannello. Grazie mille :) –

+0

L'ho provato ma non funziona, non succede nulla? –

+0

@DavidKroukamp: vedi modifica 3. –

4

Come mostrato in questo relativi FullScreenTest, è possibile utilizzare lo stesso Action istanza per il pulsante e il legame chiave.

Addendum: @nIcE mucca chiede, Possiamo aggiungere più di un tasto sulla stessaJComponentutilizzandoInputMapeActionMap, e utilizzare lo stessoAbstractActionclasse?

Sì, sono possibili più associazioni di tasti; A volte invoco doClick() per ottenere il feedback audio-visivo, come mostrato here.

+0

Posso fare una domanda su KeyBinding? Possiamo aggiungere più di una chiave sullo stesso 'JComponent' usando' InputMap' e 'ActionMap', e usare la stessa classe' AbstractAction'? –

+0

Grazie, questa mi sembra la mia unica alternativa se non riesco a far funzionare la mia versione –

Problemi correlati