如何通过单击取消选择已选择的 JRadioButton

How to deselect already selected JRadioButton by clicking on it

假设我们有一些属于同一个 ButtonGroupJRadioButton,当用户点击一个 JRadioButton 时它被选中。我想添加一个功能,当用户点击已经选择的 JRadioButton 时,它会被取消选择,即整个 ButtonGroup 将没有 JRadioButton 选择。 我已经搜索过 hint 使用 ButtonGroup 方法 clearSelection。但问题是,当用户点击已经选择的 JRadioButton 时,它不会生成任何 ItemStateChangeEvent,这是通过点击其他未选择的 JRadioButtons.

生成的

我会在按钮上使用 cited. Because a JRadioButton is a JToggleButton, a mouse gesture is possible but problematic. I'd use a MouseListener on the enclosing panel and Key Bindings 方法,如下所示。单击按钮周围的面板或按 escape 键清除 ButtonGroup.

中所有按钮的选择

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.KeyStroke;

/**
 * @see 
 */
public class Test {

    private static final String UNSELECT = "UNSELECT";

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel p = new JPanel(new GridLayout(1, 0, 5, 5));
        p.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        ButtonGroup group = new ButtonGroup();
        JRadioButton r1 = create("One", group);
        JRadioButton r2 = create("Two", group);
        p.add(r1);
        p.add(r2);
        p.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                group.clearSelection();
            }
        });
        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private JRadioButton create(String name, ButtonGroup group) {
        JRadioButton b = new JRadioButton(name);
        group.add(b);
        b.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), UNSELECT);
        b.getActionMap().put(UNSELECT, new AbstractAction(UNSELECT) {
            @Override
            public void actionPerformed(ActionEvent e) {
                group.clearSelection();
            }
        });
        return b;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Test()::display);
    }
}

或者,作为替代方法,覆盖 ButtonGroup#setSelected(...):

import java.awt.*;
import java.util.Arrays;
import javax.swing.*;

public class Test2 {
  public JComponent makeUI() {
    JPanel p = new JPanel(new GridLayout(2, 1));
      p.add(makePanel("Default ButtonGroup", new ButtonGroup()));
      p.add(makePanel("Custom ButtonGroup", new ButtonGroup() {
          private ButtonModel prevModel;
          private boolean isAdjusting = false;
          @Override public void setSelected(ButtonModel m, boolean b) {
              if (isAdjusting) {
                  return;
              }
              if (m.equals(prevModel)) {
                  isAdjusting = true;
                  clearSelection();
                  isAdjusting = false;
              } else {
                  super.setSelected(m, b);
              }
              prevModel = getSelection();
          }
      }));
    return p;
  }
  private JComponent makePanel(String title, ButtonGroup g) {
    JPanel p = new JPanel();
    p.setBorder(BorderFactory.createTitledBorder(title));
    for (String s: Arrays.asList("aaa", "bbb", "ccc")) {
      AbstractButton r = new JRadioButton(s);
      //AbstractButton r = new JToggleButton(s);
      p.add(r);
      g.add(r);
    }
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new Test2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}