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
はイベントを受信しません。しかし、そうだと確信しています。
欠けているものはありますか?
必要なすべてのコンポーネントにkeyListenerを追加する必要があります。フォーカスのあるコンポーネントのみがこれらのイベントを送信します。たとえば、JFrameにTextBoxが1つしかない場合、そのTextBoxにフォーカスがあります。そのため、このコンポーネントにもKeyListenerを追加する必要があります。
プロセスは同じです:
myComponent.addKeyListener(new KeyListener ...);
注:一部のコンポーネントは、JLabelのようにフォーカス可能ではありません。
それらをフォーカス可能に設定するには、以下を行う必要があります。
myComponent.setFocusable(true);
すべてのコンポーネントにリスナーを登録したくない場合は、
できます独自のKeyEventDispatcher
をKeyboardFocusManager
に追加:
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);
}
}
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);
KeyListener
は低レベルであり、単一のコンポーネントにのみ適用されます。 JFrame
をさらに使いやすくする試みにもかかわらず、多くのコンポーネントコンポーネントが作成されますが、最も明白なのはコンテンツペインです。 JComboBox
UIも同様の方法で実装されることがよくあります。
マウスイベントは、キーイベントとは少し異なる奇妙な方法で動作することに注意してください。
あなたがすべきことの詳細については、 アプリケーション全体のキーボードショートカット-Java Swing 。
本当の問題はJFrameがすでにリスナーを追加しているフォーカスに関するものであると読むまで同じ問題を抱えていましたが、JFrame内にフォーカス可能な多くのコンポーネントがあるため、ツアーフレームはフォーカスされません。
JFrame.setFocusable(true);
幸運を
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;
}
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;
}
}
うーん..あなたのコンストラクタはどのクラスですか?おそらく、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);
}
}
これは役立つはずです
yourJFrame.setFocusable(true);
yourJFrame.addKeyListener(new Java.awt.event.KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
System.out.println("you typed a key");
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("you pressed a key");
}
@Override
public void keyReleased(KeyEvent e) {
System.out.println("you released a key");
}
});
私は同じ問題を抱えています。ブルーノのアドバイスに従って、JFrameの「最初の」ボタン(つまり左上)にKeyListenerを追加するだけでうまくいくことがわかりました。しかし、私はあなたに同意します、それは一種の不安な解決策です。それで私はいじくり回し、それを修正するよりきれいな方法を発見しました。行を追加するだけです
myChildOfJFrame.requestFocusInWindow();
jFrameのサブクラスのインスタンスを作成して表示可能に設定した後、メインメソッドに追加します。