0

I have a JFrame and in that frame I have some JCheckBox components. Say that I have two sets of 5 check boxes.

I want to make it so that I check (for example) the first check box in the first set, the four others will be disabled. But not those in the other 'set'.

The problem is though that I do not know how to do this without writing a lot of if statements. Because in reality I have about 26 check boxes. One set of 15, and one set of 11.

I think it would be smart to figure out which check box was checked and then just disable all of them but not the one that was checked of course. But I do not know how to see which check box was set. I can only check for a specific box. E.G

 @Override
public void itemStateChanged(ItemEvent e) {
    if(e.getSource.equals(CheckBox_1){
        //dostuff
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user3685412
  • 4,057
  • 3
  • 16
  • 16

3 Answers3

5

You could write your own controller, which you would associate all the buttons in a single set together, something like...

ButtonSetController controller = ButtonSetController(
   checkBox1,
   checkBox2,
   checkBox3,
   checkBox4,
   checkBox5);

The controller would add a ActionListener to each button and monitor for changes in there states. When an appropriate state change has occurred, the controller would be able to automatically disable all the other buttons in the set...

public void actionPerformed(ActionEvent evt) {
    JCheckBox btn = (JCheckBox)evt.getSource();
    if (btn.isSelected()) {
        for (JCheckBox cb : buttons) {
            if (cb != btn) {
                cb.setSelected(false);
                cb.setEnabled(false);
            }
        }
    } // Consider re-enabling all the buttons...?
}

Now, all this would be made simpler if you used arrays of buttons as well...

You could also consider adding the buttons to ButtonGroup as well, this will ensure that only one button is selected at any one time.

See How to Use the ButtonGroup Component for more details

As a rough example

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ButtonControllerExample {

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

    public ButtonControllerExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JCheckBox[] buttons = new JCheckBox[8];
                buttons[0] = new JCheckBox("Bananas");
                buttons[1] = new JCheckBox("Grapes");
                buttons[2] = new JCheckBox("Apples");
                buttons[3] = new JCheckBox("Pears");
                buttons[4] = new JCheckBox("Kikiw");
                buttons[5] = new JCheckBox("Potatos");
                buttons[6] = new JCheckBox("Tomatoes");
                buttons[7] = new JCheckBox("Tim Tams");

                ButtonController<JCheckBox> controller = new ButtonController<>(4, buttons);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());

                for (JCheckBox cb : buttons) {
                    frame.add(cb);
                }

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

    public class ButtonController<T extends JToggleButton> {

        private List<T> selected;
        private int limit;

        public ButtonController(int limit, T... buttons) {
            if (limit <= 0) {
                throw new IllegalArgumentException("Limit can not be equal to or less then 0");
            }
            this.limit = limit;
            selected = new ArrayList<>(limit + 1);
            ItemStateHandler handler = new ItemStateHandler();
            for (T btn : buttons) {
                btn.addItemListener(handler);
            }
        }

        public class ItemStateHandler implements ItemListener {

            @Override
            public void itemStateChanged(ItemEvent e) {
                T btn = (T)e.getSource();
                if (!selected.contains(btn) && btn.isSelected()) {
                    selected.add(btn);
                    while (!selected.isEmpty() && selected.size() > limit) {
                        btn = selected.remove(0);
                        btn.setSelected(false);
                    }
                } else {
                    selected.remove(btn);
                }
            }

        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • +1 for mentioning my solution before I got it posted... think my answer is worth keeping up or should I delete it? – drew moore Jul 02 '14 at 02:03
  • @drewmoore My own feedback would be with regards to scalability, but that's just me. I have no issue with the answer generally ;) – MadProgrammer Jul 02 '14 at 02:10
  • Thanks. But what is "buttons" in the foreach loop? – user3685412 Jul 02 '14 at 02:19
  • @user3685412 Something that is iterable, for me, that would be some kind of `List` of `JButton`s, but it could be an array of `JButton`s as well – MadProgrammer Jul 02 '14 at 02:20
  • @user3685412 MadProgrammer's answer is better, but see mine for an example of what you're asking about specifically there – drew moore Jul 02 '14 at 02:22
  • 1
    Thank you so much. I looked at the link you wrote at the end and discovered JRadioButtons. Which do exactly what I wanted it to do. Thanks! – user3685412 Jul 02 '14 at 02:32
  • @user3685412 Yeah, that's what I "hoped" you wanted ;) – MadProgrammer Jul 02 '14 at 02:36
  • Dammit. Well, JRadioButton works perfect for one of the sets. Where I only want 1 single item selected. But on the other set, I want up to 6 items selected. so I guess I need to use JChechboxes. Any idea how I can find out which checkbox is checked if I use itemlistener? (Like using "System.out.println(e.getActionCommand)" if it was a JRadioButton and I used actionlistener? – user3685412 Jul 02 '14 at 02:49
  • 1
    `ItemListener` or `ActionListener` either should do. You could use the controller idea and simply keep a count of the number of items selected. I would be tempted to place each newly selected item into a `List` of some kind and when the size exceeded the limit, pop the first item off the `List` and unselect it...but that's me ;) – MadProgrammer Jul 02 '14 at 02:53
  • @user3685412 I added a rough example as a proof of concept, hope it gives you some ideas – MadProgrammer Jul 02 '14 at 03:11
1
ArrayList<JCheckBox> relatedBoxes = new ArrayList<>();
... add related boxes to your list
@Override
public void itemStateChanged(ItemEvent e) {
    JCheckBox selected = (JCheckBox) e.getSource();
    for (JCheckBox box : relatedBoxes) {
        if (!box.equals(selected)){
           box.setEnabled(false);        
           box.setSelected(false);
        }
    }
}

UPDATE: in response to your comment, now you're getting into the territory where it might be appropriate to abstract some functionality into your own List implementation. That said, something to the effect of the following would work as a quick-and-dirty solution:

ArrayList<JCheckBox> relatedBoxes = new ArrayList<>();  //consder creating class CheckBoxList extends ArrayList<JCheckBox> {}
... add related boxes to your list

@Override
public void itemStateChanged(ItemEvent e) {
    int numSelected = 0; 
    for(JCheckBox box : relatedBoxes) 
        if (box.isSelected()) numSelected++; //would be nice if you could call: if (checkBoxList.numSelected >= 6)
    if (numSelected >= 6) {
        JCheckBox selected = (JCheckBox) e.getSource();
        for (JCheckBox box : relatedBoxes) {
            if (!box.equals(selected)){
               box.setEnabled(false);        
               box.setSelected(false);
            }
        }
    } else //do something (or nothing) when less than 6 are selected
}
drew moore
  • 31,565
  • 17
  • 75
  • 112
  • Tried it, but I got an error. "the foreach loop is not applicable to type 'javax.swing.JList'" – user3685412 Jul 02 '14 at 02:22
  • @user3685412 when we say *list*, we're talking about a `java.util.List` implementation (`ArrayList`, `LinkedList`...), or any of the iterable [collection](http://docs.oracle.com/javase/tutorial/collections/) types. `JList` is a GUI component, not an iterable collection. See my edit for clarification. – drew moore Jul 02 '14 at 02:30
  • Thanks. This worked!. do you know how I could make it so it only disables the checkboxes when 6 have been selected. (so if you deselct one it will re-enable them)? – user3685412 Jul 02 '14 at 02:57
-1

see this tutorial

Hi, you can group your checkboxes using CheckBoxGroup class like this format.

CheckboxGroup fruitGroup = new CheckboxGroup();

      Checkbox chkApple = new Checkbox("Apple",fruitGroup,true);
      Checkbox chkMango = new Checkbox("Mango",fruitGroup,false);
      Checkbox chkPeer = new Checkbox("Peer",fruitGroup,false);
bumbumpaw
  • 2,522
  • 1
  • 24
  • 54
  • This answer relates to AWT and not Swing...I would consider using a `ButtonGroup`, but the OP wants to disable the other controls in the set, where a `ButtonGroup` will ensure that only on button is selected and would be better suited to `JRadioButton` – MadProgrammer Jul 02 '14 at 01:59