How to set a shortcut key for JRadioButton without modifiers

强颜欢笑 提交于 2019-12-29 01:58:30

问题


I'm working in a project where I need to add a key shortcut for each JRadioButton, while looking on another similar question and as I'm using some other custom Actions I decided to use the method setAction on each of my JRadioButtons, however it requires me to press ALT + 1 - ALT + 5 to "trigger" the actionPerformed method of my CustomAction class.

How can I modify this class in order to just press 1 - 5 and get the same behaviour?

This is the code I made that demonstrates this issue:

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

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
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");
        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++) {
            buttons[i] = new JRadioButton();
            switch (i) {
                case 0:
                    buttons[i].setAction(new CustomAction(String.valueOf(i + 1), KeyEvent.VK_1));
                    break;
                case 1:
                    buttons[i].setAction(new CustomAction(String.valueOf(i + 1), KeyEvent.VK_2));
                    break;
                case 2:
                    buttons[i].setAction(new CustomAction(String.valueOf(i + 1), KeyEvent.VK_3));
                    break;
                case 3:
                    buttons[i].setAction(new CustomAction(String.valueOf(i + 1), KeyEvent.VK_4));
                    break;
                default:
                    buttons[i].setAction(new CustomAction(String.valueOf(i + 1), KeyEvent.VK_5));
                    break;
            }
            group.add(buttons[i]);
            frame.getContentPane().add(buttons[i]);
        }

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

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

回答1:


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



来源:https://stackoverflow.com/questions/40944066/how-to-set-a-shortcut-key-for-jradiobutton-without-modifiers

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