2013-05-13 4 views
6

Я пытаюсь что-то сделать, когда одна из клавиш со стрелками нажата с помощью KeyListener в моем классе JPanel. Вот мой код:Keylistener не работает для 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) {} 
} 

Мой основной метод добавляет новый экземпляр этой панели к кадру и отображает его. Нужно ли добавлять ключевой список в JFrame? В моем случае это было бы сложно и неэффективно, поэтому я хотел бы, если возможно, работать с этим JPanel. Кто-нибудь знает, что я делаю неправильно?

EDIT: Сочетания клавиш код, который не работает, либо:

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

Может кто-нибудь сказать мне, почему это не работает либо? (мой второй прослушиватель действий для других вещей, необходимых для моей игры)

+0

Другой идеей может быть внутренний класс и использовать что-то вроде: this.addKeyListener (внутренний класс/анонимный внутренний класс); – ObedMarsh

+0

Возможный дубликат [java keylistener not called] (http://stackoverflow.com/questions/8482268/java-keylistener-not-called) –

ответ

9

Если вы ищете эту проблему, вы увидите, что ее спрашивают и она была решена много раз.

  • KeyListeners должны быть на сфокусированном компоненте для работы. Одно из решений заключается в том, чтобы дать вашему компоненту фокус после того, как он стал основным.
  • Лучше всего использовать длинный снимок, чтобы использовать привязки клавиш. Google учебник по этому вопросу.

Для получения более подробной информации см. Мой ответ this question, включая многие детали gory.

+0

Спасибо, я рассмотрю привязки клавиш, но в этом отношении я рассмотрел различные решений и не может видеть, что я делаю по-другому. Как мне настроить мой компонент? Я думал, что сделал это, используя requestFocusInWindow() – user2373733

+3

Фокусное поведение зависит от платформы; кроме того, 'KeyListener' будет хрупким в этом отношении, если есть _any_ другие фокусируемые компоненты. – trashgod

+0

@ user2373733 Ключи привязки - это путь. Просто оставьте свой KeyListener: он сэкономит вам время и избежит ошибок в будущем. –

4

Для справки я создаю пример, используя ваш подход; в то время как он работает, он также предлагает проблему фокуса в другом месте вашего кода. Key Bindings избегайте этого, как показано на рисунке here.

Приложение: Вот моя рабочая привязка ключа.

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:

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

Ах спасибо, я понятия не имею, что может быть в фокусе. Я установил все мои другие панели, которые были добавлены в мой кадр, чтобы не сфокусироваться во время тестирования, чтобы убедиться, что ничто не помешает. Я сейчас тестирую ключевые привязки, хотя у меня есть немного неприятностей, которые являются новыми для многих вещей. – user2373733

+0

Вы можете попробовать этот минимальный [пример] (http://stackoverflow.com/a/7457102/230513). – trashgod

+0

Да, это пример, который я пробовал :( – user2373733

1

я должен был сделать две вещи: я добавил comp.setFocusable (истинное); к компоненту comp, который прослушивает ключевые события, и я добавил comp.requestFocus(); к каждому действию, которое заставило comp потерять фокус.

Смежные вопросы