How to set a shortcut key for JRadioButton without modifiers

Deadly 提交于 2019-11-28 14:21:24

How do you tie any key to a component in Swing? Key Bindings: Key Bindings Tutorial.

Hang on while I look at your code...

For example

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

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class RadioButtonSelectableByNumbers {
    private JFrame frame;
    private JRadioButton buttons[];
    private ButtonGroup group;

    public RadioButtonSelectableByNumbers() {

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RadioButtonSelectableByNumbers().createAndShowGui();
            }
        });
    }

    public void createAndShowGui() {
        frame = new JFrame("frame");
        frame.setDefaultCloseOperation(JFrame);
        buttons = new JRadioButton[5];
        group = new ButtonGroup();

        frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));

        for (int i = 0; i < buttons.length; i++) {
            JRadioButton rbtn = createButton(i);
            buttons[i] = rbtn;
            frame.getContentPane().add(rbtn);
        }

        frame.pack();
        frame.setVisible(true);
    }

    private JRadioButton createButton(int i) {
        String name = String.valueOf(i + 1);
        int stdMnemonic = KeyEvent.VK_1 + i;  // for standard number keys
        int numpadMnemonic = KeyEvent.VK_NUMPAD1 + i;  // for numpad number keys
        Action action = new CustomAction(name, stdMnemonic);
        JRadioButton rBtn = new JRadioButton(action);
        group.add(rBtn);

        // bindings active if window is focused. Component doesn't have to be focused
        int condition = JComponent.WHEN_IN_FOCUSED_WINDOW; 
        InputMap inputMap = rBtn.getInputMap(condition);
        ActionMap actionMap = rBtn.getActionMap();
        KeyStroke keyStroke = KeyStroke.getKeyStroke(stdMnemonic, 0);
        KeyStroke keyStroke2 = KeyStroke.getKeyStroke(numpadMnemonic, 0);
        inputMap.put(keyStroke, keyStroke.toString());
        actionMap.put(keyStroke.toString(), action);
        inputMap.put(keyStroke2, keyStroke2.toString());
        actionMap.put(keyStroke2.toString(), action);
        return rBtn;
    }

    class CustomAction extends AbstractAction {
        public CustomAction(String name, Integer mnemonic, Integer modifier) {
            super(name);
            putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic, modifier));
        }

        public CustomAction(String name, Integer mnemonic) {
            super(name);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("radio clicked: " + e.getActionCommand());
        }
    }
}

Another solution, that may be better, since usually JRadioButtons don't use ActionListeners, is to create an AbstractAction that simply clicks the button. In the example below, MyAction does this, as well as gives the active JRadioButton the focus:

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class NumberActions extends JPanel {
    private ButtonGroup buttonGroup = new ButtonGroup();

    public NumberActions() {
        ItemListener itemListener = new MyItemListener();
        setLayout(new GridLayout(1, 0));
        for (int i = 0; i < 10; i++) {
            JRadioButton rBtn = createRadioBtn(i);
            rBtn.addItemListener(itemListener);
            buttonGroup.add(rBtn);
            add(rBtn);
        }
    }

    private JRadioButton createRadioBtn(int i) {
        String text = String.valueOf(i);
        JRadioButton rBtn = new JRadioButton(text);
        rBtn.setActionCommand(text);

        int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
        InputMap inputMap = rBtn.getInputMap(condition);
        ActionMap actionMap = rBtn.getActionMap();
        Action action = new MyAction(rBtn);

        bindAction(inputMap, actionMap, action, KeyEvent.VK_0 + i);
        bindAction(inputMap, actionMap, action, KeyEvent.VK_NUMPAD0 + i);

        return rBtn;
    }

    private void bindAction(InputMap inputMap, ActionMap actionMap, Action action, int mnemonic) {
        KeyStroke keyStroke = KeyStroke.getKeyStroke(mnemonic, 0);
        inputMap.put(keyStroke, keyStroke.toString());
        actionMap.put(keyStroke.toString(), action);
    }

    private class MyItemListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent iEvt) {
            if (iEvt.getStateChange() == ItemEvent.SELECTED) {
                AbstractButton btn = (AbstractButton) iEvt.getSource();
                System.out.println("Button: " + btn.getActionCommand());
            }
        }
    }

    private class MyAction extends AbstractAction {
        private AbstractButton btn;

        public MyAction(AbstractButton btn) {
            this.btn = btn;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            btn.requestFocusInWindow();
            btn.doClick();
        }
    }

    private static void createAndShowGui() {
        NumberActions mainPanel = new NumberActions();

        JFrame frame = new JFrame("NumberActions");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

edit: code fixed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!