私のアプリケーションでは、デフォルトボタンを使用します。 ENTER
キーがreleasedの場合に反応させたい。 ENTER
キーが押されたの場合ではありません。
ボタンのKeyStroke
からInputMap
を削除しました。しかし、それは私にはうまくいきませんでした。どうすればよいですか?
import javax.swing.*;
import Java.awt.*;
import Java.awt.event.ActionEvent;
public class ButtonTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
buildFrame();
}
});
}
private static void buildFrame() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JButton button = new JButton(new AbstractAction("Button") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("ButtonTest::actionPerformed: CALLED");
}
});
JButton button2 = new JButton("Button 2");
InputMap im = button.getInputMap();
im.put(KeyStroke.getKeyStroke("ENTER"), "none");
im.put(KeyStroke.getKeyStroke("released ENTER"), "released");
f.setLayout(new GridBagLayout());
f.add(button);
f.add(button2);
f.getRootPane().setDefaultButton(button);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
これはサンプルコードです。
JRootPane rootPane = SwingUtilities.getRootPane(/* Your JButton */);
rootPane.setDefaultButton(/* Your JButton */);
デフォルトのボタンのキー(つまり、Enterでトリガーされるボタンで、どのコンポーネントがfocusOwnerであっても)は、rootPaneのcomponentInputMap、つまりWHEN_IN_FOCUSED_WINDOWタイプのinputMapにバインドされています。だから技術的には、それは微調整する場所です:
JComponent content = new JPanel();
content.add(new JTextField("some focusable"));
content.add(new JTextField("something else"));
JXFrame frame = wrapInFrame(content, "default button on released");
Action action = new AbstractAction("do something") {
@Override
public void actionPerformed(ActionEvent e) {
LOG.info("clicked");
}
};
JButton button = new JButton(action);
content.add(button);
frame.getRootPane().setDefaultButton(button);
// remove the binding for pressed
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("ENTER"), "none");
// retarget the binding for released
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("released ENTER"), "press");
注意:これは、デフォルト以外のボタンの押された/離された動作とはまだ異なります。rootPaneアクションは、buttonModelの準備/押しの動きを介さずに、ボタンのbutton.doClickを呼び出すだけなので、アクションを間接的にトリガーします。
InputMap im = button.getInputMap();
im.put(KeyStroke.getKeyStroke("ENTER"), "pressed");
im.put(KeyStroke.getKeyStroke("released ENTER"), "released");
これの効果は、ENTERがリリースされたときにボタンがactionPerformedを1回だけ実行することです(私が正しく理解していれば、これはあなたが望んでいることです)。
編集:以下のコードを実行すると、actionPerformedがENTERのリリース時にのみ実行されることが示されます(視覚的にボタンはENTERを押したときにすでに押されているように見えます)
import javax.swing.*;
import Java.awt.*;
import Java.awt.event.ActionEvent;
public class ButtonTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
buildFrame();
}
});
}
private static void buildFrame() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JButton button = new JButton(new AbstractAction("Button") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("ButtonTest::actionPerformed: CALLED");
}
});
InputMap im = button.getInputMap();
im.put(KeyStroke.getKeyStroke("ENTER"), "pressed");
im.put(KeyStroke.getKeyStroke("released ENTER"), "released");
f.add(button);
f.getRootPane().setDefaultButton(button);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
次のように、_ getKeyStroke()
のバージョンを使用して、onKeyRelease
をtrue
に設定できます answer
編集:この answer のように、繰り返しを停止できます。