2012-06-24 9 views
7

Tengo problemas para hacer que mi KeyBoardFocusManger funcione con mi pantalla completa Window. No importa qué, simplemente no recibirá entrada de teclado. Usé un System.exit(0) y un println() para buscar cualquier llamada al método presionado/liberado/mecanografiado, pero no se lanzaron errores. Lo intenté KeyListeners; pero después de leer this, cambié a KeyboardFocusManager, y aún sucede lo mismo. Realmente me estoy desesperando; por lo que puedo juzgar, ¿el Window no está enfocando el teclado?Pantalla completa La ventana no recibirá entrada de teclado con KeyListener o KeyBoardFocusManager

Aquí es mi principal:

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

y aquí está la interfaz de usuario que contiene el KeyBoardFocusManger, y se añade en addListeners() método:

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

El botón de salida es sólo porque me cansé de matando mi aplicación a través de taskmanager. Finalmente aquí está mi panel en el cual el juego tendrá lugar y mi fondo está pintado en:

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

Gracias de antemano.

EDIT: ahora he intentado usar una combinación de teclas en mi drawingPanel pero todavía no pasa nada cuando pulso 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

No es un Marco sino una Ventana, y podría usar un botón para cerrarlo pero quiero que el Juego use la tecla 'Esc' para salir y abrir el menú, etc. –

+0

Entonces supongo que KeyBinding es exactamente lo que puede funcionar para tú. –

Respuesta

5

¿Por qué utiliza componentes AWT en su Swing GUI? Me temo (pero no estoy seguro) que al hacer esto, es posible que pierda parte de la funcionalidad de Swing.

Si solo está capturando selecciones de teclas selectas para controlar el juego, considere usar Key Bindings.

Editar:
No, los componentes AWT no tienen la culpa, pero aún así, probablemente no debe usarse.

Editar 2:
Su ventana de nivel superior no se centra por alguna razón. Continuando a probar el código ...

Datos 3:
El uso de un JFrame trabajó para mí:

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 ¡Qué estúpido de mí, estaba concentrado en agregar combinaciones de teclas a la 'Ventana', lo que obviamente es imposible, nunca pensé en agregarlo a mi panel. Muchas gracias :) –

+0

Lo probé pero no funciona, ¿no pasa nada? –

+0

@DavidKroukamp: ver edición 3. –

4

Como se muestra en esta relacionada FullScreenTest, puede utilizar la misma instancia para Action el botón y el enlace de clave.

Adición: Vaca @nIcE pide, se puede añadir más de una llave en el mismoJComponentutilizandoInputMap y ActionMap, y utilizar la misma claseAbstractAction?

Sí, son posibles múltiples enlaces de teclas; A veces invoco doClick() para obtener los comentarios audiovisuales, como se muestra en here.

+0

¿Puedo hacer una pregunta sobre KeyBinding? ¿Podemos agregar más de una clave en el mismo 'JComponent' usando' InputMap' y 'ActionMap', y usar la misma clase' AbstractAction'? –

+0

Gracias, esta parece ser mi única alternativa si no puedo hacer que mi versión funcione –

Cuestiones relacionadas