4

これらのイベントのいずれかが発生したときにイベントを発生させるための単一のボタンを備えた単純なJFrameを取得しようとしています。

  • Enterキーが押され、JButtonにフォーカスがある
  • スペースバーが押され、JButtonにフォーカスがあります
  • JButtonがクリックされます。

Enterキーとスペースバーは、JButtonでaddActionListenerを使用したデフォルトのマウスクリックとともに「無料」で提供されるようです。問題は、キーバインディングが使用されるルックアンドフィールに依存していることを読みました。

JButtonのアクションマップにEnterキーとスペースバーを追加してLaF全体で普遍的な動作を実現しようとしました。さらに、ランダムキー( "m")を追加して、ActionMapが機能していることを確認しました(実際はそうでした)が、現在はマウスです。クリックが失われます。すべてのキーとマウスクリックを取得できるように見える唯一の方法は、アクションマップとaddActionListenerの両方を使用することです。

発生する可能性のあるすべてのLaFを検出しようとせずに、これらのキーとマウスのバインディングをすべてのLaFで一貫して機能させる方法はありますか?キーイベントとマウスイベントの両方で起動するシングルアクションリスナーを登録できますか?

私のお気に入りの解決策は、JButtonアクションマップにマウスクリックを追加し、アクション内で発生したキーまたはマウスクリックを検出することです。

私はまだここでロープを学んでいるので、これはおそらく物事を行うための最良または最も効率的な方法ではありません。過剰に設計されていると確信しています。これは、私が手に入れることができるすべてのものを実験している一種のトレーニング演習です。あらゆるコーディングスタイルのコメントを歓迎します!

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;

public class Example extends JFrame {

// ============================
private class BtnListener extends AbstractAction {
    private static final long serialVersionUID = 1L;

    public void actionPerformed(ActionEvent ae) {
        System.out.println("\nclick button listener triggered");
        System.out.println(ae.getSource().getClass().toString());
    }
} // class BtnListener

private static final int NO_MODIFIER = 0;
private static final boolean ON_KEY_PRESS = false;
private static final KeyStroke ENTER_PRESSED = KeyStroke.getKeyStroke(
        KeyEvent.VK_ENTER, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke M_PRESSED = KeyStroke.getKeyStroke(
        KeyEvent.VK_M, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke SPACEBAR_PRESSED = KeyStroke.getKeyStroke(
        KeyEvent.VK_SPACE, NO_MODIFIER, ON_KEY_PRESS);
private JButton btnButton;
private final AbstractAction btnListener = new BtnListener();
private JPanel buttonPanel;
private JFrame frmMain;

public static void main(String[] args) {
    Example ex = new Example();
    ex.displayFrame();
}

Action btnActionListener = new AbstractAction() {
    private static final long serialVersionUID = 1L;

    public void actionPerformed(ActionEvent e) {
        System.out.println("\nkey button action triggerred");
        System.out.println(e.getSource().getClass().toString());
        if (e.getSource() instanceof JButton) {
            System.out.println("button");
        } else {
            System.out.println("Something else");
        }
    }
};

public Example() {
    initialize();
}

public void displayFrame() {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Throwable e) {
        e.printStackTrace();
    }
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                frmMain.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

private void initialize() {

    frmMain = new JFrame();
    btnButton = new JButton("Abutton");

    // Comment this out, you lose the mouse click
    btnButton.addActionListener(btnListener);

    // Comment out ActionMaps, but keep addActionListner (above), and
            // only lose M_PRESSED
    InputMap buttonFocusedMap = btnButton
            .getInputMap(JComponent.WHEN_FOCUSED);

    buttonFocusedMap.put(ENTER_PRESSED, "blah");
    btnButton.getActionMap().put("blah", btnActionListener);

    buttonFocusedMap.put(SPACEBAR_PRESSED, "blort");
    btnButton.getActionMap().put("blort", btnActionListener);

    buttonFocusedMap.put(M_PRESSED, "gaaak");
    btnButton.getActionMap().put("gaaak", btnActionListener);

    // Is there a way to add a mouse click to the ActionMap?

    buttonPanel = new JPanel();
    buttonPanel.add(btnButton);

    frmMain.getContentPane().add(buttonPanel);
    frmMain.setBounds(100, 100, 500, 432);
    frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

}
4

2 に答える 2

9

BasicButtonListenerによって使用されBasicButtonUI、フォーカスされたときにすべてのボタン(チェック、ラジオ、トグル)がバインドされていることを確認します。Spaceこれは、個々のルックアンドフィールがさまざまなボタンモデルの状態を一意にレンダリングする場合でも、プラットフォーム間で機能します。押すとSpace押された を呼び、UIAction離すと解放れたを呼びます。マウスがボタンの範囲内で押されて放されたときにも同じことが起こります。押したままボタンの外側にドラッグして、武装状態の変化を確認します。Space UIAction

いずれの場合も、押された状態と離された状態の組み合わせにより、ボタンのメソッド呼び出されます。actionPerformed()

Enterフォーカスに関係なく、にバインドする便利な方法の1つActionは、ルートペインのsetDefaultButton()メソッドを使用することです。このは、ボタンをクリックする3つの方法すべてを示しています。

于 2012-05-23T01:08:38.233 に答える
0

あなたができる(そしておそらくすべき)ことは、AbstractActionを作成することです。AbstractActionは、ActionMapとクリックの両方に使用できます(do JButton.setAction(...))

于 2012-05-22T22:00:35.970 に答える