web-dev-qa-db-ja.com

キーリスナーがJPanelで機能しない

JPanelクラスのKeyListenerを使用して矢印キーの1つが押されたときに、何かをしようとしています。これが私のコードです:

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で動作させたいと思います。誰かが私が間違っていることを知っていますか?

編集:どちらも機能しないキーバインディングコード:

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

なぜこれも機能しないのか誰かに教えてもらえますか? (私の2番目のアクションリスナーは、私のゲームに必要な他のもののためのものです)

8
user2373733

この問題を検索すると、質問され、何度も解決されていることがわかります。

  • KeyListenersが機能するには、フォーカスされたコンポーネント上にある必要があります。 1つの解決策は、最初にコンポーネントをフォーカス可能にした後で、コンポーネントにフォーカスを与えることです。
  • ただし、長い目で見れば、キーバインディングを使用することをお勧めします。これに関するチュートリアルをグーグル。

この質問 に対する私の答えを見てください。これについては、多くの厄介な詳細を含めて、詳しく説明しています。

参考までに、私はあなたのアプローチを使用して例を作成しました。それが機能している間、それはまたあなたのコードの他の場所で焦点の問題を示唆します。 キーバインディング 示されているように、これを避けてください ここ

補遺:これが私の作業キーバインディングです。

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();
            }
        });
    }
}
5
trashgod

JPanelで重要なイベントを受信するには、フォーカスを設定する必要があります。

setFocusable(true);
requestFocus(); 

JPanelにフォーカスがあるため、重要なイベントを受信します

0
Dmitriy Potapov

私は2つのことをしなければなりませんでした:comp.setFocusable(true);を追加しました。キーイベントをリッスンするコンポーネントcompに、comp.requestFocus();を追加しました。コンプがフォーカスを失う原因となった各アクションに。

0
Donald Smith