Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

java - Fire a JButton with spacebar, or enter key, or mouse click

I'm trying to get a simple JFrame with a single button to fire an event when any of these events happen:

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

It seems that the Enter and Spacebar come "for free" along with the default mouse click using addActionListener on the JButton; trouble is, I've read that the the key bindings are dependent on the Look and Feel used.

I've tried to get universal behavior across LaF by adding Enter and Spacebar to the JButton's action map, and even added a random key ("m") to make sure the ActionMap was doing the work (it was), but now the mouse click is lost. The only way I seem to be able to get all the keys and mouse click is to use both action map and addActionListener.

Is there a way to get these key and mouse bindings to work consistently across all LaF without trying to detect every possible LaF that may come along? Can I register a single action listener that will fire on both key and mouse events?

My favorite solution would be to add a mouse click to the JButton action map and detect which key or mouse click happened inside the inside the action.

I'm still learning the ropes here, so this probably isn't the best or most efficient way to do things; I'm sure it's over-engineered. This is sort of training exercise where I'm experimenting with everything I can get my hands on. Any and all coding style comments are welcome!

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("
click 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("
key 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);
}

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

BasicButtonListener, used by BasicButtonUI, ensures that all buttons (check, radio, toggle) are bound to Space when focused. This works across platforms, even though individual Look & Feels may render various button model states uniquely. Pressing Space evokes the pressed UIAction, and releasing Space evokes the released UIAction. The same occurs when the mouse is pressed and released within the button's bounds; drag outside the button while pressed to see the armed state change.

In either case, the combination of pressed and released invokes your button's actionPerformed() method.

One convenient way to bind Enter to an Action, irrespective of focus, is via the root pane's setDefaultButton() method. This example illustrates all three ways to click a button.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...