Запустите JButton с помощью пробела, или введите клавишу, или щелкните мышью

Я пытаюсь получить простой JFrame с одной кнопкой для запуска события, когда происходит любое из этих событий:

The Enter key is pressed AND the JButton has focus The Spacebar is pressed AND the JButton has focus The JButton is clicked.

Кажется, что Enter и пробел приходят "бесплатно" наряду с щелчком мыши по умолчанию с использованием addActionListener на JButton; Проблема в том, что я читал, что привязки клавиш зависят от используемого внешнего вида и ощущения.

Я пытался добиться универсального поведения в LaF, добавив Enter и пробел к карте действий JButton, и даже добавил случайный ключ (& quot; m & quot;), чтобы убедиться, что 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);
}

}

Ответы на вопрос(2)

Решение Вопроса

BasicButtonListener, использованBasicButtonUIгарантирует, чтоall кнопки (проверка, радио, переключатель) связаны сSpace когда сосредоточены. Это работает на разных платформах, даже если отдельные Look & amp; Чувства могут отображать различные состояния модели кнопок однозначно. прессованиеSpace вызываетpressed UIActionи выпускаяSpace вызываетreleased UIAction, То же самое происходит, когда мышь нажимают и отпускают в пределах кнопки; потяните за кнопку, чтобы увидеть изменение режима охраны.

В любом случае комбинацияpressed а такжеreleased вызывает ваши кнопкиactionPerformed() метод.

Один удобный способ связатьEnter дляActionнезависимо от фокуса, через корневую панельsetDefaultButton() метод. этопример иллюстрирует все три способа нажатия кнопки.

 Paul N23 мая 2012 г., 21:11
Отлично! Спасибо за глубокое объяснение.

Что вы можете (и, вероятно, должны) сделать, это создать AbstractAction. Вы можете использовать AbstractAction как для ActionMap, так и для нажатия (сделайте JButton.setAction (...))

Ваш ответ на вопрос