简体   繁体   中英

Java, If multiple checkboxes are ticked?

I'm creating a simple program where the user can tick checkboxes for different colors. If several boxes are ticked then it should show what the mix of the colors are going to be. Example blue and yellow is ticked then the label shows green. I got 3 problems.

  1. Checking multiple colors dont mix like the above example.
  2. Unchecking a checkbox dont change the label.
  3. When all of them are uncheck it should go back to "No colors chosen".

class LabDemo extends JFrame implements ActionListener {
    JLabel displayColor = new JLabel("No chosen color");
    JCheckBox blue = new JCheckBox("Blue");
    JCheckBox yellow = new JCheckBox("Yellow");
    JCheckBox red = new JCheckBox("Red");
    JPanel panel = new JPanel();

    public LabDemo() {
        panel.setLayout(new GridLayout(4,1));
        blue.addActionListener(this);
        yellow.addActionListener(this);
        red.addActionListener(this);
        this.add(panel);
        displayColor.setBackground(Color.WHITE);
        panel.add(blue); panel.add(yellow); panel.add(red); panel.add(displayColor);
        setSize(300,300);
        setLocation(100,100);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (blue.isSelected()) {
            displayColor.setText("Blue");
            panel.setBackground(Color.BLUE);
        }
        else if (yellow.isSelected()) {
            displayColor.setText("Yellow");
            panel.setBackground(Color.YELLOW);
        }
        else if (red.isSelected()) {
            displayColor.setText("Red");
            panel.setBackground(Color.RED);
        }
        else if (blue.isSelected() && yellow.isSelected()) {
            displayColor.setText("Blue + Yellow = Green");
            panel.setBackground(Color.GREEN);
        }
    }
}

You will never enter in the last case (blue and yellow), because you are in an if-else, and one of the above statements will be evaluated true before that (the blue one alone, in this case). If the cases are just those four, the "blue and yellow" one should be put at the first thing to check.

Another option: assign each checked option a binary place value, sum the values for the three checkboxes, and switch on that sum:

switch ((red.isSelected() ?   1 : 0) +
        (green.isSelected() ? 2 : 0) +
        (blue.isSelected() ?  4 : 0))
{
    case 0: // none selected
    case 1: // RED selected
    case 2: // GREEN selected
    case 3: // RED + GREEN
    case 4: //  BLUE
    case 5: // BLUE + RED
    case 6: // BLUE + GREEN
    case 7: // RED + BLUE + GREEN
}

As I mentioned in comment, better to use Red, Green, and Blue, since you're dealing with additive colors, such as colors from light beams, not subtractive colors such as colors from paints. If you were dealing with subtractive colors, then Red, Yellow and Blue would be appropriate, but again, that is not the situation here.

Another option to a solution is to use an enum to represent your colors, something like this:

import java.awt.Color;

public enum MyColor {
    RED("Red", Color.RED), 
    GREEN("Green", Color.GREEN), 
    BLUE("Blue", Color.BLUE);

    private String name;
    private Color color;

    private MyColor(String name, Color color) {
        this.name = name;
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public Color getColor() {
        return color;
    }
}

Then we can get an array of these objects via MyColor.values() and use it to create the JCheckBoxes. If we put the checkboxes into a collection, such as a Map, we can check the state of all of them when the state of one changes:

private Map<MyColor, JCheckBox> colorMap = new EnumMap<>(MyColor.class);

private class CheckListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        // initial individual color values
        int r = 0;
        int g = 0;
        int b = 0;

        // iterate through the check boxes, seeing which are selected
        for (MyColor myColor : MyColor.values()) {

            // if selected, extract its colors and add to rgb values
            if (colorMap.get(myColor).isSelected()) {
                r += myColor.getColor().getRed();
                g += myColor.getColor().getGreen();
                b += myColor.getColor().getBlue();
            }
        }

        // let's avoid going beyond the maximum values allowed
        r = Math.min(r, 255);
        g = Math.min(g, 255);
        b = Math.min(b, 255);

        // create a color with the values and set the JPanel
        Color color = new Color(r, g, b);
        colorPanel.setBackground(color);
    }
}

The GUI could look like so:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;

@SuppressWarnings("serial")
public class ColorExample extends JPanel {
    private JPanel colorPanel = new JPanel();
    private Map<MyColor, JCheckBox> colorMap = new EnumMap<>(MyColor.class);

    public ColorExample() {
        colorPanel.setPreferredSize(new Dimension(400, 300));
        colorPanel.setBackground(Color.BLACK);

        JPanel gridPanel = new JPanel(new GridLayout(1, 0));
        CheckListener checkListener = new CheckListener();
        for (MyColor myColor : MyColor.values()) {
            JCheckBox checkBox = new JCheckBox(myColor.getName());
            checkBox.addActionListener(checkListener);
            colorMap.put(myColor, checkBox);
            gridPanel.add(checkBox);
        }

        setLayout(new BorderLayout());
        add(colorPanel);
        add(gridPanel, BorderLayout.PAGE_END);
    }

    private class CheckListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // initial individual color values
            int r = 0;
            int g = 0;
            int b = 0;

            // iterate through the check boxes, seeing which are selected
            for (MyColor myColor : MyColor.values()) {

                // if selected, extract its colors and add to rgb values
                if (colorMap.get(myColor).isSelected()) {
                    r += myColor.getColor().getRed();
                    g += myColor.getColor().getGreen();
                    b += myColor.getColor().getBlue();
                }
            }

            // let's avoid going beyond the maximum values allowed
            r = Math.min(r, 255);
            g = Math.min(g, 255);
            b = Math.min(b, 255);

            // create a color with the values and set the JPanel
            Color color = new Color(r, g, b);
            colorPanel.setBackground(color);
        }
    }

    private static void createAndShowGui() {
        ColorExample mainPanel = new ColorExample();

        JFrame frame = new JFrame("Color Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM