如何在没有修饰符的情况下为 JRadioButton 设置快捷键

How to set a shortcut key for JRadioButton without modifiers

我在一个项目中工作,我需要为每个 JRadioButton 添加一个快捷键,同时查看另一个 similar question 并且因为我正在使用其他一些自定义 Actions 我决定在每个 JRadioButtons 上使用方法 setAction,但是它需要我按 ALT + 1 - ALT + 5 到 "trigger" actionPerformed 我的方法 CustomAction class.

如何修改此 class 以便仅按 1 - 5 并获得相同的行为?

这是我编写的演示此问题的代码:

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

如何将任意键绑定到 Swing 中的组件?按键绑定:Key Bindings Tutorial.

请稍等,我会查看您的代码...

例如

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

另一个可能更好的解决方案,因为通常 JRadioButtons 不使用 ActionListeners,是创建一个只需单击按钮的 AbstractAction。在下面的示例中,MyAction 执行此操作,并为活动的 JRadioButton 提供焦点:

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

编辑:代码已修复