Search code examples
javaswingcoding-stylecode-reusejcheckbox

How to avoid redundant coding with JCheckBoxes in Java


I have a set of classes that implement a particular interface and I have a set of checkboxes. I want to throw an error if no checkboxes are selected. If atleast one or more checkboxes are selected, then it should create objects associated with that checkbox.

This is how I done.

interface U { ... }

class A implements U { ... }
class B implements U { ... }
class C implements U { ... }

class Main {
    //.... 
    //....
    public void findSelectedCheckBoxesAndCreateObjects() {
        if(!(checkboxA.isSelected() || checkboxB.isSelected() || checkboxC.isSelected()) {
            System.out.println("No checkboxes selected");
            return;
        }

        //if any selected, create associated object
        if(checkboxA.isSelected()) new A(file);
        if(checkboxB.isSelected()) new B(file);
        if(checkboxC.isSelected()) new C(file);
    }
}

Now I have 3 problems.

  1. This is just a sample code. Original has 8 checkboxes and classes with more coming.
  2. I can't keep adding || checkboxD.isSelected() every time I have a new class for checking it.
  3. Same thing. I can't keep adding if(checkboxD.isSelected()) new D(file); for every class.

It is very inelegant. Can I have some kind of loop that removes the redundant code?

Please give me your suggestions. Thank you.


Solution

  • You should use a collection structure to hold your checkboxes and those related classes. Using a Map you could do something like this:

    Map <JCheckBox,Class<U>> uCheck = new HashMap<JCheckBox,Class<U>>();

    // add your checkboxes and U-classes to the map

    uCheck.put(checkBoxA, A.class);
    

    Now, it's quite easy to get a collection of the classes that need to be instantiated based on the checkbox status:

    public Collection<Class<U>>  getEnabledClasses(<JCheckBox,Class<U>> checkMap) {
        List<Class<U>> result = new LinkedList<Class<U>>();
        for (Map.Entry<JCheckBox,Class<U>> entry:checkMap.entrySet()) {
            if (entry.getKey().isSelected()) {
                result.add(entry.getValue());
            }
        }
    }
    

    Now, a call to getEnabledUs(uCheck) returns a collection of the selected classes. If the collection is empty, there's no selection, hence nothing to do.

    for (Class<U> u:getEnabledClasses(...)) {
        Constructor<U> cons = u.getConstructor(...);
        U instance = cons.newInstance(fileparameter);
        instance.doSomething(...);
    }
    

    That should get you started. (*) Disclaimer: this is non-tested code. Rather pseudo-code with crisp detail only where needed.