2011-12-12 52 views
7

He escrito un código de ejemplo usando KeyListener en Java, He creado un JPanel, luego establezco su enfocable en verdadero, he creado un KeyListener, solicité un foco y luego agregué el KeyListener a mi panel. Pero los métodos para keyListener nunca se llaman. Parece que aunque he solicitado el enfoque, no se enfoca.java keylistener no se llama

¿Alguien puede ayudar?

listener = new KeyLis(); 
this.setFocusable(true); 
this.requestFocus(); 
this.addKeyListener(listener); 

class KeyLis implements KeyListener{ 

    @Override 
    public void keyPressed(KeyEvent e) { 
     currentver += 5; 
     switch (e.getKeyCode()) { 
      case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5; 
       break; 
      case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5; 
       break; 
     } 
     repaint(); 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyTyped(KeyEvent e) { 
    } 
} 

caso de necesitar cualquier código ejecutable:

import java.awt.Color; 
    import java.awt.Graphics; 
    import java.util.Random; 

    import javax.swing.JFrame; 
    import javax.swing.JLabel; 


public class test extends JFrame { 

private AreaOfGame areaOfGame; 

public test() 
{ 
    super(""); 
    setVisible(true); 
    this.setBackground(Color.darkGray); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    this.pack(); 
    setLayout(null); 
    setBounds(200, 10, 400, 700); 

    areaOfGame = new AreaOfGame(); 
    this.add(areaOfGame); 

    startGame(); 
} 

public int generateNext() 
{ 
    Random r = new Random(); 
    int n = r.nextInt(7); 
    return n; 
} 

public void startGame() 
{ 
    while(!areaOfGame.GameOver()) 
    { 
     areaOfGame.startGame(generateNext()); 
    } 
} 


public static void main(String[] args) { 
    new MainFrame(); 
} 


import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 

import javax.swing.JPanel; 

public class AreaOfGame extends JPanel { 


    private static final int rightside = 370; 

    private int bottom; 
    private int top; 

    private int currentPos; 
    private int currentver; 
    private KeyLis listener; 

    public AreaOfGame() 
    { 
     super(); 

     bottom = 650; 
     top = 50; 
     setLayout(null); 
     setBounds(20, 50, 350, 600); 
     setVisible(true); 


     this.setBackground(Color.lightGray); 

     listener = new KeyLis(); 
     this.setFocusable(true); 
     if(this.requestFocus(true)) 
      System.out.println("true");; 
     this.addKeyListener(listener); 


     currentPos = 150; 
     currentver=0; 
    } 

    public void startGame(int n) 
    { 
     while(verticallyInBound()){ 
      System.out.println("anything"); 

     } 


    } 

    public boolean verticallyInBound() 
    { 
     if(currentPos<= bottom -50) 
      return true; 
     return false; 
    } 


    public boolean GameOver() 
    { 
     if(top>= bottom){ 
      System.out.println("game over"); 
      return true; 
     } 

     else return false; 
    } 


    public boolean horizontalyInBounds() 
    { 
     if(currentPos<=rightside && currentPos>= 20) 
      return true; 
     else return false; 
    } 


class KeyLis implements KeyListener{ 

     @Override 
     public void keyPressed(KeyEvent e) { 
      System.out.println("called"); 
      currentver += 5; 
      switch (e.getKeyCode()) { 
       case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5; break; 
       case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5; break; 
      } 
      repaint(); 


     } 

     @Override 
     public void keyReleased(KeyEvent e) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void keyTyped(KeyEvent e) { 
      System.out.println("called 3"); 
     } 
} 

} 
+1

Sería de gran ayuda si nos pudiera dar a su clase "KeyLis", tal vez no es el problema. – eboix

+0

gracias, agregué la clase de escucha – BBB

+0

Hmmm ... Creo que tuve un problema similar al mismo tiempo. Intente llamar al método "e.consume()" al final de su método keyPressed (KeyEvent e). Déjame saber si funciona. – eboix

Respuesta

12

apuesto a que usted está solicitando enfoque antes de la JPanel se ha rendido (antes de la ventana de nivel superior o bien ha tenido pack() o setVisible(true) llamado), y si es así, esto no funcionará. La solicitud de enfoque solo se otorgará posiblemente después de que se hayan procesado los componentes. ¿Ha revisado cómo ha regresado su llamada al requestFocus()? Debe ser cierto para que su llamada tenga alguna posibilidad de éxito. También es mejor usar requestFocusInWindow() en lugar de requestFocus().

Pero lo que es más importante, no debe usar KeyListeners para esto, sino enlaces de teclas, un concepto de nivel superior que Swing utiliza para responder a las pulsaciones de teclas.

Editar
Un ejemplo de un SSCCE:

import java.awt.Dimension; 
import java.awt.event.*; 
import javax.swing.*; 

public class TestKeyListener extends JPanel { 
    private KeyLis listener; 

    public TestKeyListener() { 
     add(new JButton("Foo")); // something to draw off focus 
     listener = new KeyLis(); 
     this.setFocusable(true); 
     this.requestFocus(); 
     this.addKeyListener(listener); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(300, 200); 
    } 

    private class KeyLis extends KeyAdapter { 
     @Override 
     public void keyPressed(KeyEvent e) { 
     switch (e.getKeyCode()) { 
     case KeyEvent.VK_LEFT: 
      System.out.println("VK_LEFT pressed"); 
      break; 
     case KeyEvent.VK_RIGHT: 
      System.out.println("VK_RIGHT pressed"); 
      break; 
     } 
     } 
    } 

    private static void createAndShowGui() { 
     TestKeyListener mainPanel = new TestKeyListener(); 

     JFrame frame = new JFrame("TestKeyListener"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

Editar 2
y el equivalente SSCCE utilizando la clave Bindings:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class TestKeyBindings extends JPanel { 

    public TestKeyBindings() { 
     add(new JButton("Foo")); // something to draw off focus 
     setKeyBindings(); 
    } 

    private void setKeyBindings() { 
     ActionMap actionMap = getActionMap(); 
     int condition = JComponent.WHEN_IN_FOCUSED_WINDOW; 
     InputMap inputMap = getInputMap(condition); 

     String vkLeft = "VK_LEFT"; 
     String vkRight = "VK_RIGHT"; 
     inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft); 
     inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight); 

     actionMap.put(vkLeft, new KeyAction(vkLeft)); 
     actionMap.put(vkRight, new KeyAction(vkRight)); 

    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(300, 200); 
    } 

    private class KeyAction extends AbstractAction { 
     public KeyAction(String actionCommand) { 
     putValue(ACTION_COMMAND_KEY, actionCommand); 
     } 

     @Override 
     public void actionPerformed(ActionEvent actionEvt) { 
     System.out.println(actionEvt.getActionCommand() + " pressed"); 
     } 
    } 

    private static void createAndShowGui() { 
     TestKeyBindings mainPanel = new TestKeyBindings(); 

     JFrame frame = new JFrame("TestKeyListener"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

Editar 3
Con respecto a su SSCCE reciente, sus bucles while (true) están bloqueando su secuencia de eventos Swing y pueden impedir que se produzca la interacción o pintura del usuario. Es mejor utilizar un temporizador de oscilación en lugar de while (true). Por ejemplo:

import java.awt.*; 
import java.awt.event.*; 
import java.util.Random; 

import javax.swing.*; 

public class BbbTest extends JFrame { 

    private AreaOfGame areaOfGame; 

    public BbbTest() { 
     super(""); 
//  setVisible(true); 
     this.setBackground(Color.darkGray); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.pack(); 
     setLayout(null); 
     setBounds(200, 10, 400, 700); 

     areaOfGame = new AreaOfGame(); 
     this.add(areaOfGame); 
     setVisible(true); 

     startGame(); 
    } 

    public int generateNext() { 
     Random r = new Random(); 
     int n = r.nextInt(7); 
     return n; 
    } 

    public void startGame() { 
     // while (!areaOfGame.GameOver()) { 
     // areaOfGame.startGame(generateNext()); 
     // } 

     areaOfGame.startGame(generateNext()); 
    } 

    public static void main(String[] args) { 
     new BbbTest(); 
    } 

    class AreaOfGame extends JPanel { 

     private static final int rightside = 370; 

     private int bottom; 
     private int top; 

     private int currentPos; 
     private int currentver; 
     private KeyLis listener; 

     public AreaOfGame() { 
     super(); 

     bottom = 650; 
     top = 50; 
     setLayout(null); 
     setBounds(20, 50, 350, 600); 
     setVisible(true); 

     this.setBackground(Color.lightGray); 

     listener = new KeyLis(); 
     this.setFocusable(true); 
     if (this.requestFocus(true)) 
      System.out.println("true"); 
     ; 
     this.addKeyListener(listener); 

     currentPos = 150; 
     currentver = 0; 
     } 

     public void startGame(int n) { 
     // while (verticallyInBound()) { 
     // System.out.println("anything"); 
     // } 

     int timeDelay = 50; // msecs delay 
     new Timer(timeDelay , new ActionListener() { 

      public void actionPerformed(ActionEvent arg0) { 
       System.out.println("anything"); 
      } 
     }).start(); 

     } 

     public boolean verticallyInBound() { 
     if (currentPos <= bottom - 50) 
      return true; 
     return false; 
     } 

     public boolean GameOver() { 
     if (top >= bottom) { 
      System.out.println("game over"); 
      return true; 
     } 

     else 
      return false; 
     } 

     public boolean horizontalyInBounds() { 
     if (currentPos <= rightside && currentPos >= 20) 
      return true; 
     else 
      return false; 
     } 

     class KeyLis implements KeyListener { 

     @Override 
     public void keyPressed(KeyEvent e) { 
      System.out.println("called"); 
      currentver += 5; 
      switch (e.getKeyCode()) { 
      case KeyEvent.VK_LEFT: 
       if (horizontalyInBounds()) 
        currentPos -= 5; 
       break; 
      case KeyEvent.VK_RIGHT: 
       if (horizontalyInBounds()) 
        currentPos += 5; 
       break; 
      } 
      repaint(); 

     } 

     @Override 
     public void keyReleased(KeyEvent e) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void keyTyped(KeyEvent e) { 
      System.out.println("called 3"); 
     } 
     } 
    } 
} 
+0

En realidad, todo esto se hace después de que mi cuadro tenga pack() y setVisible (verdadero). Si usar enlaces de teclas es la única opción, lo haré, pero me gustaría saber por qué esto no funciona, porque ningún cuerpo parecía para tener este problema antes, busqué punteros nulos, enfoques, métodos llamados, el oyente agregado pero no trabajado. – BBB

+0

@BBB: de nuevo, ¿has verificado con tu método 'requestFocus()' la llamada ha regresado? ¿Está regresando verdadero o falso? –

+0

devuelve falso todo el tiempo – BBB

0

Es posible utilizar el botón "TAB" para alternar entre los botones y el oyente de la tecla. Tengo un programa con un botón que después de presionarlo, el oyente de la tecla no funciona. Me di cuenta de que si presiona el botón "TAB", la "Atención" o "foco" del programa vuelve al oyente de la tecla.

Tal vez esto ayude: http://docstore.mik.ua/orelly/java-ent/jfc/ch03_08.htm