2013-05-13 11 views
6

Sto provando a fare qualcosa quando uno dei tasti freccia viene premuto utilizzando il KeyListener nella mia classe JPanel. Ecco il mio codice:Keylistener non funziona per 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) {} 
} 

Il mio metodo principale aggiunge una nuova istanza di questo pannello a una cornice e la visualizza. Devo aggiungere il keylistener alla JFrame? Nel mio caso, questo sarebbe difficile e inefficiente, quindi mi piacerebbe farlo funzionare con questo JPanel se possibile. Qualcuno sa cosa sto sbagliando?

EDIT: codice chiave Attacchi che non funziona neanche:

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

Qualcuno mi può dire perché questo non funziona neanche? (il mio secondo listener di azioni è per altre cose necessarie per il mio gioco)

+0

Un'altra idea potrebbe essere creare una classe interna e utilizzare qualcosa come: "this.addKeyListener (inner class/anonimo inner class);" – ObedMarsh

+0

possibile duplicato di [java keylistener non chiamato] (http://stackoverflow.com/questions/8482268/java-keylistener-not-called) –

risposta

9

Se cerchi questo problema, vedrai che è stato chiesto ed è stato risolto molte volte.

  • I keylisteners devono essere sul componente focalizzato per funzionare. Una soluzione è dare al tuo componente la messa a fuoco dopo averlo prima messo a fuoco.
  • Meglio per un lungo tiro, tuttavia, è quello di utilizzare i tasti di scelta rapida. Google il tutorial su questo.

Si prega di dare un'occhiata alla mia risposta a this question per ulteriori informazioni su questo, compresi molti dei dettagli cruenti.

+0

Grazie, cercherò le associazioni chiave, ma per questo aspetto ho visto varie soluzioni e non riesco a vedere cosa sto facendo in modo diverso. Come faccio a focalizzare il mio componente? Ho pensato di farlo utilizzando requestFocusInWindow() – user2373733

+3

Il comportamento del focus varia a seconda della piattaforma; inoltre, un 'KeyListener' sarà fragile a questo riguardo se ci sono _anche altre componenti focalizzabili. – trashgod

+0

@ user2373733 Le associazioni di tasti sono la strada da percorrere. Basta rilasciare KeyListener: ti farà risparmiare tempo ed eviterà futuri bug. –

4

Per riferimento, ho creato un esempio utilizzando il tuo approccio; mentre funziona, suggerisce anche un problema di messa a fuoco in altre parti del codice. Key Bindings evitare questo, come mostrato here.

Addendum: ecco la mia chiave di lavoro vincolante.

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 originale:

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 grazie, non ho idea di cosa potrebbe essere il focus. Ho impostato tutti gli altri pannelli che sono stati aggiunti alla mia cornice in modo da non sfociare durante i test, per assicurarmi che nulla interferisse. Sto provando i binding principali ora, anche se sto avendo un po 'di problemi ad essere nuovo in molte di queste cose – user2373733

+0

Potresti provare questo minimo [esempio] (http://stackoverflow.com/a/7457102/230513). – trashgod

+0

Sì, questo è l'esempio che ho provato :( – user2373733

1

ho dovuto fare due cose: ho aggiunto comp.setFocusable (true); al componente comp che ascolta gli eventi chiave, e ho aggiunto comp.requestFocus(); ad ogni azione che ha causato il comp di perdere la messa a fuoco.