在Java Swing中取消选择单选按钮

41
当展示一组JRadioButtons时,初始状态下没有一个被选中(除非您通过编程强制执行)。我希望能够在用户已经选择其中一个之后,将按钮重新放回到该状态,即没有任何一个按钮被选中。
然而,使用通常的方法并不能达到所需的效果:对每个按钮调用“setSelected(false)”无效。有趣的是,当按钮没有放入ButtonGroup时,它确实起作用-不幸的是,后者是JRadioButtons互斥所必需的。
此外,使用javax.swing.ButtonGroup的setSelected(ButtonModel, boolean)方法也不能满足我的要求。
我编写了一个小程序来演示这种效果:两个单选按钮和一个JButton。单击JButton应取消选中单选按钮,以便窗口看起来与首次弹出时完全相同。
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;

/**
 * This class creates two radio buttons and a JButton. Initially, none
 * of the radio buttons is selected. Clicking on the JButton should
 * always return the radio buttons into that initial state, i.e.,
 * should disable both radio buttons.
 */
public class RadioTest implements ActionListener {
    /* create two radio buttons and a group */
    private JRadioButton button1 = new JRadioButton("button1");
    private JRadioButton button2 = new JRadioButton("button2");
    private ButtonGroup group = new ButtonGroup();

    /* clicking this button should unselect both button1 and button2 */
    private JButton unselectRadio = new JButton("Unselect radio buttons.");

    /* In the constructor, set up the group and event listening */
    public RadioTest() {
        /* put the radio buttons in a group so they become mutually
         * exclusive -- without this, unselecting actually works! */
        group.add(button1);
        group.add(button2);

        /* listen to clicks on 'unselectRadio' button */
        unselectRadio.addActionListener(this);
    }

    /* called when 'unselectRadio' is clicked */
    public void actionPerformed(ActionEvent e) {
        /* variant1: disable both buttons directly.
         * ...doesn't work */
        button1.setSelected(false);
        button2.setSelected(false);

        /* variant2: disable the selection via the button group.
         * ...doesn't work either */
        group.setSelected(group.getSelection(), false);
    }

    /* Test: create a JFrame which displays the two radio buttons and
     * the unselect-button */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        RadioTest test = new RadioTest();

        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new GridLayout(3,1));
        contentPane.add(test.button1);
        contentPane.add(test.button2);
        contentPane.add(test.unselectRadio);

        frame.setSize(400, 400);
        frame.setVisible(true);
    }
}

有什么想法吗?谢谢!

这里展示了一个使用键绑定的示例:链接 - trashgod
11个回答

64

1
太棒了!这就解释了为什么ButtonGroup的Javadoc删除了关于不可见RadioButton的部分...(现在,如果他们能添加一个关于clearSelection的部分就好了;-)) - Thomas

7
该类的Javadoc(ButtonGroup)本身就提供了一些关于如何实现这一目标的提示:
从类ButtonGroup的API文档中可以看出:最初,组中所有按钮都未被选中。一旦选择了任何一个按钮,组中总有一个按钮被选中。没有办法通过编程方式将按钮设置为“关闭”,以清除按钮组。为了呈现“未选择”的外观,请向组添加一个不可见的单选按钮,然后通过编程方式选择该按钮以关闭所有显示的单选按钮。

1
哦,我的天啊...我觉得有些奇怪,因为我之前已经阅读过API文档了。现在,你知道吗:原来你引用的那部分已经从Java 6的API文档中删除了!请参见此处进行比较:http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ButtonGroup.html(Java 5)和http://java.sun.com/javase/6/docs/api/javax/swing/ButtonGroup.html(Java 6)。难怪我在文档中找不到任何东西... - Thomas
@Thomas - 我同意。胡说八道。呕。 - JasCav

4
您可以使用点击计数器:
private ButtonGroup radioGroup = new javax.swing.ButtonGroup();
private JRadioButton jRadioBtn1 = new javax.swing.JRadioButton();
private int clickCount = 0;

private void jRadioBtn1Clicked(java.awt.event.MouseEvent evt) {                                             
    // Remove selection on a second click
    if (jRadioBtn1.isSelected()) {

        if (++clickCount % 2 == 0) {

            radioGroup.clearSelection();
        }
    }
}   

4

尝试向按钮组添加第三个不可见的按钮。当你想要“取消选择”时,选择不可见的按钮。


3
或者你可以使用Darryl的选择按钮组,它不需要你使用“隐形按钮”。

0
使用这个辅助类SelectButtonGroup.java,可以直接访问类source
import java.awt.*;
import java.awt.event.ActionListener;
import javax.swing.*;

public class SelectUnselected extends JPanel {
    private static String birdString = "Bird";
    private static String catString = "Cat";
    private static Integer selectedIndex = -1;
    private static AbstractButton hiddenButton = new JRadioButton(catString);
    private final static AbstractButton birdButton = new JRadioButton(birdString);
    private final static AbstractButton catButton = new JRadioButton(catString);
    //Group the radio buttons.
    private SelectButtonGroup group = new SelectButtonGroup();

public SelectUnselected() {
    super(new BorderLayout());

    //Create the radio buttons.
    hiddenButton.setVisible(false);
    hiddenButton.setSelected(true);

    group.add(birdButton);
    group.add(catButton);
    group.add(hiddenButton);


    ActionListener sendListener = e -> {
        checkSelectedRadioButten();
    };
    birdButton.addActionListener(sendListener);
    catButton.addActionListener(sendListener);
    hiddenButton.addActionListener(sendListener);



    //Put the radio buttons in a column in a panel.
    JPanel radioPanel = new JPanel(new GridLayout(0, 1));
    radioPanel.add(birdButton);
    radioPanel.add(catButton);

    add(radioPanel, BorderLayout.LINE_START);
    setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}

public void checkSelectedRadioButten(){

    System.out.println("selectedIndex = " + selectedIndex + "\ngroup.getSelectedButton() = " + group.getSelectedIndex());
    if(group.getSelectedIndex() == selectedIndex){
        hiddenButton.setSelected(true);
        selectedIndex = -1;
        System.out.println("getText = " + group.getSelectedButton().getText());
    }else{
        selectedIndex = group.getSelectedIndex();
        System.out.println("getText = " + group.getSelectedButton().getText());
    }
}

public static void main(String[] args) {
    JFrame frame = new JFrame("RadioButtonDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JComponent newContentPane = new SelectUnselected();
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);

    }
}

0

你可以使用自己的 ButtonGroup(1),或者使用修改后的实例(2),就像这样: 仅适用于 JAVA 6 以后:

(1) public class NoneSelectedButtonGroup extends ButtonGroup {
  @Override
  public void setSelected(ButtonModel model, boolean selected) {
    if (selected) {
      super.setSelected(model, selected);
    } else {
      clearSelection();
    }
  }
}

(2) ButtonGroup chGroup = new ButtonGroup() {
            @Override
            public void setSelected(ButtonModel m, boolean b) {
                if (!b) clearSelection();
                else
                    super.setSelected(m, b);
            }
        };

https://blog.frankel.ch/unselect-all-toggle-buttons-of-a-group/中获取


0

我不知道这是否有帮助,但你尝试过使用doClick()方法吗?

jRadioButtonYourObject.doClick();

输入 - 无

返回 - void

我曾经遇到过类似的问题,尝试了这个线程中的所有方法,但都没有成功。所以我查看了JRadioButton的所有方法,并找到了其父类的方法。

在我的程序中,我有两个互不相关的单选按钮,并编写了程序,使得只能选择其中一个。

用户输入数据并点击按钮后,程序会清除所有文本字段和区域,并取消选择单选按钮。 doClick() 方法可以帮助我取消选择单选按钮;该方法“执行”了一个“单击”操作。

我知道你的情况可能不同,你可能需要为每个选定的单选按钮编写 doClick() 方法。

http://docs.oracle.com/javase/7/docs/api/javax/swing/AbstractButton.html

搜索 doClick()


你尝试使用过 doClick() 方法吗?[...] 我之前也遇到了类似的问题,试了这个帖子里的所有方法都没用。但是我选择的正确答案对我很有用。 - Thomas

0

您可以使用setselected(false)方法来取消选择先前选定的按钮。


正如我在问题中所说(第二段),那对我没有起作用。您能否提供一个代码示例来演示您的意思? - Thomas

0

在我的情况下,我使用Jgoodies项目将GUI组件绑定到Java模型。RadioButton组件绑定到一个字段。

class Model {
  private SomeJavaEnum field; // + getter, setter
}

在这种情况下,ButtonGroup.clearSelection 不起作用,因为旧值仍然保留在模型中。直接的解决方案是简单地使用 setField(null)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接