0

I'm making a UI involving a lot of radiobuttons and buttonGroups in NetBeans. Suppose 2 radiobuttons are assigned to the same buttonGroup. Once you click on one of the radiobutton it's becoming impossible to deselect it. What can I do so that if a user clicks on it again the readiobuttons are deselected? Here's my attempt:

if (b1.isSelected()==true) {
   b1.setEnabled(false); 
}

But I don't wanna end up disabling it. Help me out.

Edit: Here's a cheap way to do it:

int k=0;
private void mb1ActionPerformed(java.awt.event.ActionEvent evt) {                                    
if (mb1.isSelected()==true) { //mb1 is the radiobutton
    k++;
}
if (k%2==0) {
    buttonGroup1.clearSelection();
}

yea but this makes the UI messy, sometimes the radiobuttons in the buttongroup have to be clicked on twice to select them again.

P. Pawar
  • 23
  • 8
  • I'm wondering if you can use `ButtonGroup#setSelected(ButtonModel, boolean)` – MadProgrammer Aug 15 '18 at 23:05
  • Possible duplicate [Unselecting RadioButtons in Java Swing](https://stackoverflow.com/questions/2408689/unselecting-radiobuttons-in-java-swing) – MadProgrammer Aug 15 '18 at 23:06
  • 1
    Side note: `if(b1.isSelected()==true)` and `if(b1.isSelected())` is equivalent while the latter bears less risc of introducing errors on your side. – Thomas Aug 15 '18 at 23:20
  • @MadProgrammer I tried that. What happens is if I do that it gets deselected but then re-selection is not possible – P. Pawar Aug 15 '18 at 23:29
  • https://stackoverflow.com/questions/43678934/reset-a-radio-button-inside-a-radio-group My problem is similar to this, but that is coded in C, and most importantly ".tag" is used which doesn't work in java or in Netbeans atleast – P. Pawar Aug 15 '18 at 23:32

1 Answers1

0

Okay, this bit of a hack. There are a number of problems which are difficult to solve.

ButtonGroup is a concrete class, so making a customised version is difficult (and this is why I like interfaces), it's further complicated as it relies very heavily on private (or package private) properties, which doesn't provide any reasonable extension point

So, this leaves two courses of action, either use reflection or copy the base class and make our own modifications - neither case is pleasant.

So, of all the code I copied, I only modified one method...

public void setSelected(ButtonModel m, boolean b) {
    if (b) {
        if (m != selection) {
            ButtonModel oldSelection = selection;
            selection = m;
            if (oldSelection != null && oldSelection != m) {
                oldSelection.setSelected(false);
            }
            m.setSelected(true);
        }
    } else if (selection != null) {
        ButtonModel oldSelection = selection;
        selection = null;
        oldSelection.setSelected(false);
    }
}

Basically, this now supports deselecting the current element

public class UnselectableButtonGroup extends ButtonGroup {

    // the list of buttons participating in this group
    protected Vector<AbstractButton> buttons = new Vector<AbstractButton>();

    /**
     * The current selection.
     */
    ButtonModel selection = null;

    /**
     * Creates a new <code>ButtonGroup</code>.
     */
    public UnselectableButtonGroup() {
    }

    /**
     * Adds the button to the group.
     *
     * @param b the button to be added
     */
    public void add(AbstractButton b) {
        if (b == null) {
            return;
        }
        buttons.addElement(b);

        if (b.isSelected()) {
            if (selection == null) {
                selection = b.getModel();
            } else {
                b.setSelected(false);
            }
        }

        b.getModel().setGroup(this);
    }

    /**
     * Removes the button from the group.
     *
     * @param b the button to be removed
     */
    public void remove(AbstractButton b) {
        if (b == null) {
            return;
        }
        buttons.removeElement(b);
        if (b.getModel() == selection) {
            selection = null;
        }
        b.getModel().setGroup(null);
    }

    /**
     * Clears the selection such that none of the buttons in the
     * <code>ButtonGroup</code> are selected.
     *
     * @since 1.6
     */
    public void clearSelection() {
        if (selection != null) {
            ButtonModel oldSelection = selection;
            selection = null;
            oldSelection.setSelected(false);
        }
    }

    /**
     * Returns all the buttons that are participating in this group.
     *
     * @return an <code>Enumeration</code> of the buttons in this group
     */
    public Enumeration<AbstractButton> getElements() {
        return buttons.elements();
    }

    /**
     * Returns the model of the selected button.
     *
     * @return the selected button model
     */
    public ButtonModel getSelection() {
        return selection;
    }

    /**
     * Sets the selected value for the <code>ButtonModel</code>. Only one
     * button in the group may be selected at a time.
     *
     * @param m the <code>ButtonModel</code>
     * @param b <code>true</code> if this button is to be selected,
     * otherwise <code>false</code>
     */
    public void setSelected(ButtonModel m, boolean b) {
        if (b) {
            if (m != selection) {
                ButtonModel oldSelection = selection;
                selection = m;
                if (oldSelection != null && oldSelection != m) {
                    oldSelection.setSelected(false);
                }
                m.setSelected(true);
            }
        } else if (selection != null) {
            ButtonModel oldSelection = selection;
            selection = null;
            oldSelection.setSelected(false);
        }
    }

    /**
     * Returns whether a <code>ButtonModel</code> is selected.
     *
     * @return <code>true</code> if the button is selected, otherwise
     * returns <code>false</code>
     */
    public boolean isSelected(ButtonModel m) {
        return (m == selection);
    }

    /**
     * Returns the number of buttons in the group.
     *
     * @return the button count
     * @since 1.3
     */
    public int getButtonCount() {
        if (buttons == null) {
            return 0;
        } else {
            return buttons.size();
        }
    }

}

I also investigated using an ItemListener and a ChangeListener (and both) on the buttons to try and control the state of the ButtonModel

I also tried Select Button Group but it didn't work for me (I didn't spend any time trying to debug it, but it's possible it might still work for other people)

Runnable Example...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            UnselectableButtonGroup bg = new UnselectableButtonGroup();
            JRadioButton buttons[] = new JRadioButton[5];
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            for (int index = 0; index < buttons.length; index++) {
                buttons[index] = new JRadioButton("Button " + index);
                add(buttons[index], gbc);
                bg.add(buttons[index]);
            }
        }

    }

    public class UnselectableButtonGroup extends ButtonGroup {

        // the list of buttons participating in this group
        protected Vector<AbstractButton> buttons = new Vector<AbstractButton>();

        /**
         * The current selection.
         */
        ButtonModel selection = null;

        /**
         * Creates a new <code>ButtonGroup</code>.
         */
        public UnselectableButtonGroup() {
        }

        /**
         * Adds the button to the group.
         *
         * @param b the button to be added
         */
        public void add(AbstractButton b) {
            if (b == null) {
                return;
            }
            buttons.addElement(b);

            if (b.isSelected()) {
                if (selection == null) {
                    selection = b.getModel();
                } else {
                    b.setSelected(false);
                }
            }

            b.getModel().setGroup(this);
        }

        /**
         * Removes the button from the group.
         *
         * @param b the button to be removed
         */
        public void remove(AbstractButton b) {
            if (b == null) {
                return;
            }
            buttons.removeElement(b);
            if (b.getModel() == selection) {
                selection = null;
            }
            b.getModel().setGroup(null);
        }

        /**
         * Clears the selection such that none of the buttons in the
         * <code>ButtonGroup</code> are selected.
         *
         * @since 1.6
         */
        public void clearSelection() {
            if (selection != null) {
                ButtonModel oldSelection = selection;
                selection = null;
                oldSelection.setSelected(false);
            }
        }

        /**
         * Returns all the buttons that are participating in this group.
         *
         * @return an <code>Enumeration</code> of the buttons in this group
         */
        public Enumeration<AbstractButton> getElements() {
            return buttons.elements();
        }

        /**
         * Returns the model of the selected button.
         *
         * @return the selected button model
         */
        public ButtonModel getSelection() {
            return selection;
        }

        /**
         * Sets the selected value for the <code>ButtonModel</code>. Only one
         * button in the group may be selected at a time.
         *
         * @param m the <code>ButtonModel</code>
         * @param b <code>true</code> if this button is to be selected,
         * otherwise <code>false</code>
         */
        public void setSelected(ButtonModel m, boolean b) {
            if (b) {
                if (m != selection) {
                    ButtonModel oldSelection = selection;
                    selection = m;
                    if (oldSelection != null && oldSelection != m) {
                        oldSelection.setSelected(false);
                    }
                    m.setSelected(true);
                }
            } else if (selection != null) {
                ButtonModel oldSelection = selection;
                selection = null;
                oldSelection.setSelected(false);
            }
        }

        /**
         * Returns whether a <code>ButtonModel</code> is selected.
         *
         * @return <code>true</code> if the button is selected, otherwise
         * returns <code>false</code>
         */
        public boolean isSelected(ButtonModel m) {
            return (m == selection);
        }

        /**
         * Returns the number of buttons in the group.
         *
         * @return the button count
         * @since 1.3
         */
        public int getButtonCount() {
            if (buttons == null) {
                return 0;
            } else {
                return buttons.size();
            }
        }

    }

}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366