82

私はKeyListener自分のためにを実装しようとしていJFrameます。コンストラクターでは、次のコードを使用しています。

System.out.println("test");
addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) { System.out.println( "tester"); }

    public void keyReleased(KeyEvent e) { System.out.println("2test2"); }

    public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});

実行するとtest、コンソールにメッセージが表示されます。ただし、キーを押してKeyListenerも、そこにさえないかのように、他のメッセージは表示されません。

JFrame
に焦点が当てられてKeyListenerおらず、イベントを受け取らないからかもしれないと思っていました。しかし、私はそれが正しいと確信しています。

足りないものはありますか?

4

12 に答える 12

133

すべてのコンポーネントにリスナーを登録したくない場合は、独自のリスナーを に追加でき
ます。KeyEventDispatcherKeyboardFocusManager

public class MyFrame extends JFrame {    
    private class MyDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println("tester");
            } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                System.out.println("2test2");
            } else if (e.getID() == KeyEvent.KEY_TYPED) {
                System.out.println("3test3");
            }
            return false;
        }
    }
    public MyFrame() {
        add(new JTextField());
        System.out.println("test");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}
于 2009-09-04T14:09:36.470 に答える
52

必要なすべてのコンポーネントに keyListener を追加する必要があります。フォーカスのあるコンポーネントのみがこれらのイベントを送信します。たとえば、JFrame に TextBox が 1 つしかない場合、その TextBox にフォーカスがあります。したがって、このコンポーネントにも KeyListener を追加する必要があります。

プロセスは同じです。

myComponent.addKeyListener(new KeyListener ...);

注: 一部のコンポーネントは、JLabel のようにフォーカスできません。

それらをフォーカス可能に設定するには、次のことが必要です。

myComponent.setFocusable(true);
于 2008-11-13T13:01:28.513 に答える
16

InputMapsとActionMapsは、コンポーネント、そのコンポーネントとそのすべてのサブコンポーネント、またはウィンドウ全体の主要なイベントをキャプチャするように設計されています。これは、JComponent.getInputMap()のパラメーターを介して制御されます。ドキュメントについては、キーバインディングの使用方法を参照してください。

この設計の利点は、監視するのに重要なキーストロークを選択して選択し、それらのキーストロークに基づいてさまざまなアクションを実行できることです。

このコードは、ウィンドウ内のどこかでエスケープキーが押されたときに、JFrameでdispose()を呼び出します。JFrameはJComponentから派生していないため、キーバインディングを作成するにはJFrameで別のコンポーネントを使用する必要があります。コンテンツペインはそのようなコンポーネントである可能性があります。

InputMap inputMap; 
ActionMap actionMap;
AbstractAction action;
JComponent component;

inputMap  = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();

action    = new AbstractAction()
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      dispose();
   }
};

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);
于 2013-02-23T00:29:07.607 に答える
10

KeyListener低レベルで、単一のコンポーネントにのみ適用されます。より使いやすくするための試みにもかかわらずJFrame、多くのコンポーネント コンポーネントが作成されます。最も明白なのはコンテンツ ペインです。JComboBoxUI も同様の方法で実装されることがよくあります。

マウス イベントは、キー イベントとは少し異なる奇妙な方法で動作することに注意してください。

何をすべきかの詳細については、アプリケーション全体のキーボードショートカット - Java Swingに関する私の回答を参照してください。

于 2008-11-13T13:18:58.853 に答える
9

Deion(および同様の質問をする他の人)は、上記のPeterのコードを使用できますが、標準出力に出力する代わりに、キーコードPRESSED、RELEASED、またはTYPEDをテストします。

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getID() == KeyEvent.KEY_PRESSED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_RELEASED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_TYPED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    }
    return false;
}
于 2011-01-09T14:50:07.940 に答える
4

JFrame内のすべてのテキスト フィールドのキー イベントをキャプチャするために、キー イベント ポスト プロセッサを使用できます。明らかなインクルードを追加した後の実際の例を次に示します。

public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
    public static final long serialVersionUID = 1L;

    public KeyListenerF1Demo() {
        setTitle(getClass().getName());

        // Define two labels and two text fields all in a row.
        setLayout(new FlowLayout());

        JLabel label1 = new JLabel("Text1");
        label1.setName("Label1");
        add(label1);

        JTextField text1 = new JTextField(10);
        text1.setName("Text1");
        add(text1);

        JLabel label2 = new JLabel("Text2");
        label2.setName("Label2");
        add(label2);

        JTextField text2 = new JTextField(10);
        text2.setName("Text2");
        add(text2);

        // Register a key event post processor.
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(this);
    }

    public static void main(String[] args) {
        JFrame f = new KeyListenerF1Demo();
        f.setName("MyFrame");
        f.pack();
        f.setVisible(true);
    }

    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        // Check for function key F1 pressed.
        if (ke.getID() == KeyEvent.KEY_PRESSED
                && ke.getKeyCode() == KeyEvent.VK_F1) {

            // Get top level ancestor of focused element.
            Component c = ke.getComponent();
            while (null != c.getParent())
                c = c.getParent();

            // Output some help.
            System.out.println("Help for " + c.getName() + "."
                    + ke.getComponent().getName());

            // Tell keyboard focus manager that event has been fully handled.
            return true;
        }

        // Let keyboard focus manager handle the event further.
        return false;
    }
}
于 2011-07-15T19:47:38.677 に答える
2

うーん..あなたのコンストラクターはどのクラスですか?おそらくJFrameを拡張するクラスですか?もちろん、ウィンドウのフォーカスはウィンドウにあるはずですが、それが問題だとは思いません。

私はあなたのコードを展開し、それを実行しようとしましたが、うまくいきました.キーを押すと印刷出力が得られました. (Eclipse を介して Ubuntu で実行):

public class MyFrame extends JFrame {
    public MyFrame() {
        System.out.println("test");
        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                System.out.println("tester");
            }

            public void keyReleased(KeyEvent e) {
                System.out.println("2test2");
            }

            public void keyTyped(KeyEvent e) {
                System.out.println("3test3");
            }
        });
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}
于 2008-11-13T10:39:13.753 に答える
1

私も同じ問題を抱えています。ブルーノのアドバイスに従って、JFrameの「最初の」ボタン(左上)にKeyListenerを追加するだけでうまくいくことがわかりました。しかし、私はあなたに同意します。それは一種の不安な解決策です。それで、私はいじくり回して、それを修正するためのより良い方法を発見しました。行を追加するだけです

myChildOfJFrame.requestFocusInWindow();

JFrameのサブクラスのインスタンスを作成し、それを表示するように設定した後、メインメソッドに追加します。

于 2011-01-04T02:31:37.200 に答える
-3

笑 ....あなたがしなければならないのは、それを確認することだけです

addKeyListener(これ);

コードに正しく配置されます。

于 2012-07-10T19:24:10.000 に答える
-3

カスタム JComponents に親 JFrame をフォーカス可能に設定させることができます。

コンストラクターを追加して、JFrame を渡すだけです。次に、paintComponent で setFocusable() を呼び出します。

このようにして、他のコンポーネントが押されているかどうかに関係なく、JFrame は常に KeyEvents を受け取ります。

于 2012-11-09T20:22:18.297 に答える