tags:

views:

39

answers:

3

I'm very new to Java and am having some issues looping through JCheckBoxes on a UI. The idea is that I have a bunch of checkboxes (not in a group because more than one can be selected.) When I click a JButton, I want to build a string containing the text from each selected checkbox. The issue I'm having is that our instructor told us that the checkboxes need to be created via a method, which means (see code below) that there isn't a discrete instance name for each checkbox. If there were, I could say something like

if(checkBox1.isSelected()) {
  myString.append(checkBox.getText());
}

That would repeat for checkBox2, checkBox3, and so on. But the method provided to us for adding checkboxes to a panel looks like this:

public class CheckBoxPanel extends JPanel {
private static final long serialVersionUID = 1L;

public CheckBoxPanel(String title, String... options) {
    setBorder(BorderFactory.createTitledBorder(BorderFactory
            .createEtchedBorder(), title));
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

    // make one checkbox for each option
    for (String option : options) {
        JCheckBox b = new JCheckBox(option);
        b.setActionCommand(option);
        add(b);
    }
}

}

This is called like this:

toppingPanel = new CheckBoxPanel("Each Topping $1.50", "Tomato", "Green Pepper", 
                                    "Black Olives", "Mushrooms", "Extra Cheese",
                                    "Pepperoni", "Sausage");

So I now have a panel that contains a border with the title "Each Topping $1.50", and 7 visible checkboxes. What I need to do is get a list of all the selected toppings. We are not supposed to use an ActionListener for each checkbox, but rather get the list when a button is clicked. I'm feeling really clueless here, but I just can't figure out how to get the isSelected property of the checkboxes when the individual checkboxes don't have instance names.

Ideally I'd like to somehow add all the checkboxes to an array and loop through the array in the button's action listener to determine which ones are checked, but if I have to check each one individually I will. I just can't figure out how to refer to an individual checkbox when they've been created dynamically.

+1  A: 

I suggest you maintain a list of checkboxes:

List<JCheckBox> checkboxes = new ArrayList<JCheckBox>();

and before add(b) do:

checkboxes.add(b);

You may then iterate through the list of checkboxes in the buttons action-code using a "for-each" loop construct:

for (JCheckBox cb : checkboxes)
    if (cb.isSelected())
        process(cb.getText()); // or whatever.

Alternatively, if you need to keep track of the specific index:

for (int i = 0; i < checkboxes.size(); i++)
    if (checkboxes.get(i).isSelected())
        ....
aioobe
I'll give that a shot - thanks.
EmmyS
OK, I added the List and checkboxes.add(b) to the .java file that contains the create button code (CheckBoxPanel.java). However, the action listener is in a different java file, and when I try to add the loop, the for line - for (JCheckBox cb : checkboxes) - tells me checkboxes cannot be resolved. The two files are in the same package, and the CheckBoxPanel class is a public class, but I apparently cannot access the checkboxes variable in my other .java file. Help!
EmmyS
+2  A: 

I'm assuming you're not allowed to alter the CheckBoxPanel code at all. Which seems like a useless exercise, because in the real world, you'd think that if CheckBoxPanel where a class being provided to you (e.g. in a library) it would include a way of getting the selected options. Anyway, due to the limitation, you could do something like this:

for( int i=0; i<checkBoxPanel.getComponentCount(); i++ ) {
  JCheckBox checkBox = (JCheckBox)checkBoxPanel.getComponent( i );
  if( checkBox.isSelected() ) {
     String option = checkBox.getText();
     // append text, etc
  }
}
staticman
No, I can change it somewhat (i.e. add new functionality) as long as I don't remove any of the existing code.
EmmyS
Thanks, your solution worked. I'm assuming your "real world" way of the CheckBoxPanel class providing a way to get selected options would be similar to aioobe's response. I did try that, but got an Eclipse error that I couldn't figure out how to get rid of. (See my comment to that answer.)
EmmyS
I have a second class called RadioButtonPanel that does have a getter method for the selected option (the body of which is just return group.getSelection().getActionCommand(), where group is a ButtonGroup). I'm assuming you mean that there should be something like that in the CheckBoxPanel. I'm not sure how that would work, though - the radio button is simple because there can only be one selected at a time; the getSelection method is not available for checkboxes, because they aren't part of a group (in this case, anyway, since we need to be able to select multiples.)
EmmyS
aioobe's response would be better for a "real world" solution - Keeping a reference to the checkboxes as they are created as described in the first block of code. Then provide a getSelectedOptions() method that spins through the checkboxes and builds a list of selected options as described in the second block of code.
staticman
So it's a combination of the two - use aioobe's solution to add the checkboxes to an array (or list), but then use your suggestion of creating a getter method inside the CheckBoxPanel class to get the values. That should get rid of the error I was receiving (I hope!) Thanks. After 13 years of procedural programming, this OO stuff is kicking my butt!
EmmyS
A: 

I would suggest that you dont put each of the checkboxes in a List when you create them. Instead, in your shared ActionListener, you maintain a Set of all selected checkboxes. Use the getSource method on the ActionEvent to identify which checkbox the user selected and then cast it to a JCheckBox. If isSelected() returns true for the item in question, attempt to add it to your selectedItems Set. If it is not, then attempt to remove it.

You can then just iterate over the subset of all items (only those that are selected) and print them to the console.

akf
If I'm understanding you correctly, this means that each checkbox needs to have the action listener, and the action is evaluated as soon as the box is checked or unchecked. That's exactly what we were told NOT to do. Not necessarily because it's wrong, or bad practice, but that's what the assignment is and I can't change things. I have to work with what I'm given. That said, the answer was helpful for future reference, so thanks.
EmmyS