2013-05-13 4 views
6

J'essaie de faire quelque chose quand l'une des touches fléchées est pressée en utilisant le KeyListener dans ma classe JPanel. Voici mon code:Keylistener ne fonctionne pas pour JPanel

public class TestPanel extends JPanel implements KeyListener{ 

    public TestPanel(){ 
     this.addKeyListener(this); 
     this.setFocusable(true); 
     this.requestFocusInWindow(); 
    } 

    public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
      System.out.println("Right"); 

     } 

     if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
      System.out.println("Left"); 
     } 

    } 

    public void keyTyped(KeyEvent e) {} 
    public void keyReleased(KeyEvent e) {} 
} 

Ma principale méthode ajoute une nouvelle instance de ce panneau à un cadre et l'affiche. Ai-je besoin d'ajouter le keylistener au JFrame? Dans mon cas, cela serait difficile et inefficace, donc je voudrais que cela fonctionne avec ce JPanel si possible. Quelqu'un sait ce que je fais mal?

EDIT: Code clés qui ne Manchettes fonctionne pas non plus:

public class GamePanel extends JPanel implements ActionListener{ 

//Constructor 
public GamePanel(){ 

    setupKeyBinding(); 
    this.setFocusable(true); 
    this.requestFocusInWindow(); 


} 

private void setupKeyBinding() { 
    int condition = JComponent.WHEN_IN_FOCUSED_WINDOW; 
    InputMap inMap = getInputMap(condition); 
    ActionMap actMap = getActionMap(); 

    inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left"); 
    actMap.put("Left", new leftAction()); 
} 

private class leftAction extends AbstractAction { 

     public void actionPerformed(ActionEvent e) { 
      System.out.println("test"); 
     } 
} 

public void actionPerformed(ActionEvent e) { 
    //some other game info 
} 
} 

Quelqu'un peut-il me dire pourquoi ce travail ne marche pas non plus? (mon deuxième écouteur d'action est pour d'autres choses nécessaires pour mon jeu)

+0

Une autre idée pourrait être de créer une classe interne et d'utiliser quelque chose comme: "this.addKeyListener (classe interne/classe interne anonyme);" – ObedMarsh

+0

duplication possible de [java keylistener non appelé] (http://stackoverflow.com/questions/8482268/java-keylistener-not-called) –

Répondre

9

Si vous recherchez ce problème, vous verrez qu'il est demandé et a été résolu plusieurs fois. Les KeyListeners doivent être sur le composant ciblé pour fonctionner.

  • Une solution consiste à donner la priorité à votre composant après l'avoir mis au point.
  • Mieux vaut toutefois utiliser des raccourcis clavier. Google le tutoriel sur ce sujet.

S'il vous plaît jeter un oeil à ma réponse à this question pour plus à ce sujet, y compris beaucoup de détails sanglants.

+0

Merci, je vais regarder dans les raccourcis clavier, mais pour cette question j'ai regardé divers solutions et ne peut pas voir ce que je fais différemment. Comment puis-je donner le focus à mon composant? Je pensais l'avoir fait en utilisant requestFocusInWindow() – user2373733

+3

Le comportement du focus varie en fonction de la plateforme; de plus, un KeyListener sera fragile à cet égard s'il y a d'autres composants focalisables. – trashgod

+0

@ user2373733 Les raccourcis clavier sont la solution idéale. Il suffit de déposer votre KeyListener: cela vous permettra d'économiser du temps et d'éviter de futurs bugs. –

4

Pour référence, j'ai créé un exemple en utilisant votre approche; Bien que cela fonctionne, il suggère également un problème de mise au point ailleurs dans votre code. Key Bindings éviter cela, comme indiqué here. Addendum: Voici ma liaison de clé de travail.

private static class TestPanel extends JPanel { 

    private static final String LEFT = "Left"; 
    private Action left = new AbstractAction(LEFT) { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println(LEFT); 
     } 
    }; 
    private static final String RIGHT = "Right"; 
    private Action right = new AbstractAction(RIGHT) { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println(RIGHT); 
     } 
    }; 

    public TestPanel() { 
     this.getInputMap().put(
      KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), LEFT); 
     this.getActionMap().put(LEFT, left); 
     this.getInputMap().put(
      KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), RIGHT); 
     this.getActionMap().put(RIGHT, right); 
    } 
} 

SSCCE Original:

import java.awt.EventQueue; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* @see https://stackoverflow.com/a/16531380/230513 
*/ 
public class Test { 

    private void display() { 
     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new TestPanel()); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    private static class TestPanel extends JPanel implements KeyListener { 

     public TestPanel() { 

      this.addKeyListener(this); 
      this.setFocusable(true); 
      this.requestFocusInWindow(); 
     } 

     @Override 
     public void keyPressed(KeyEvent e) { 
      if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
       System.out.println("Right"); 
      } 

      if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
       System.out.println("Left"); 
      } 
     } 

     @Override 
     public void keyTyped(KeyEvent e) { 
     } 

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

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test().display(); 
      } 
     }); 
    } 
} 
+1

Ah merci, je n'ai aucune idée de ce qui pourrait prendre la mise au point. J'ai mis tous mes autres panneaux à être ajouté à mon cadre pour ne pas faire de mise au point tout en testant pour s'assurer que rien n'interférerait. J'essaie maintenant des raccourcis clavier, bien que j'aie un peu de mal à être nouveau dans beaucoup de ces choses – user2373733

+0

Vous pourriez essayer cet exemple minimal (http://stackoverflow.com/a/7457102/230513). – trashgod

+0

Oui, c'est l'exemple que j'ai essayé :( – user2373733

1

je devais faire deux choses: j'ai ajouté comp.setFocusable (true); à la comp composant qui écoute les événements clés, et j'ai ajouté comp.requestFocus(); à chaque action qui a causé la perte de l'accent.

Questions connexes