2013-05-13 19 views
6

Próbuję coś zrobić, gdy jeden z klawiszy strzałek zostanie naciśnięty przy użyciu KeyListener w mojej klasie JPanel. Oto mój kod:Keylistener nie działa dla 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) {} 
} 

Moja główna metoda dodaje nową instancję tego panelu do ramki i wyświetla ją. Czy muszę dodać keylistener do JFrame? W moim przypadku byłoby to trudne i nieefektywne, dlatego chciałbym, aby działało to z JPanelem, jeśli to możliwe. Czy ktoś wie, co robię źle?

EDIT: Kod klawiszy, które nie działa albo:

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

Czy ktoś może mi powiedzieć, dlaczego to robi praca albo? (mój drugi słuchacz jest dla innych rzeczy potrzebnych do mojej gry)

+0

Innym pomysłem może być stworzenie wewnętrznej klasy i użycie czegoś takiego: "this.addKeyListener (wewnętrzna klasa/anonimowa klasa wewnętrzna);" – ObedMarsh

+0

możliwy duplikat [java keylistener nie wywoływana] (http://stackoverflow.com/questions/8482268/java-keylistener-not-called) –

Odpowiedz

9

Jeśli przeszukasz ten problem, zobaczysz, że jest on często zadawany i został rozwiązany.

  • KeyListeners muszą być na skoncentrowanym komponencie do pracy. Jednym z rozwiązań jest skupienie się na swoim elemencie po uprzednim skupieniu się na nim.
  • Lepiej jednak dzięki długim ujęciom można użyć powiązań klawiszy. Google samouczek na ten temat.

Proszę spojrzeć na moją odpowiedź na this question po więcej informacji na ten temat, w tym wiele szczegółów.

+0

Dzięki, zajrzę do kluczowych powiązań, ale w tej sprawie przyjrzałem się różnym rozwiązania i nie widzę, co robię inaczej. Jak mogę skupić się na moim komponencie? Myślałem, że zrobiłem to za pomocą requestFocusInWindow() – user2373733

+3

Zachowanie ostrości zależy od platformy; co więcej, 'KeyListener' będzie kruche pod tym względem, jeśli istnieją inne inne komponenty, które można skupiać. – trashgod

+0

@ user2373733 Key binding jest drogą do zrobienia. Po prostu upuść KeyListener: zaoszczędzi ci to trochę czasu i uniknie przyszłych błędów. –

4

Dla przykładu, stworzyłem przykład przy użyciu twojego podejścia; chociaż działa, sugeruje również problem z ostrzeżeniem w innym miejscu kodu. Key Bindings unikaj tego, jak pokazano here.

Dodatek: Oto moje powiązanie z kluczem roboczym.

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

Original SSCCE:

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 dzięki, nie mam pojęcia, co może skupić uwagę. Ustawiłem wszystkie moje inne panele dodawane do mojej ramki, aby nie można było je rozogniskować podczas testowania, aby upewnić się, że nic nie będzie przeszkadzać. Teraz wypróbowuję wiązania klawiszy, ale mam trochę problemów z nowościami w tej dziedzinie. – user2373733

+0

Możesz spróbować tego minimalnego [przykład] (http://stackoverflow.com/a/7457102/230513). – trashgod

+0

Tak, to jest przykład, który próbowałem :( – user2373733

1

musiałem zrobić dwie rzeczy: Dodałem comp.setFocusable (true); do kompu komponentu, który słucha kluczowych zdarzeń, i dodałem comp.requestFocus(); do każdego działania, które spowodowało, że komp stracił ostrość.