Java,如果勾选了多个复选框?

Java, If multiple checkboxes are ticked?

我正在创建一个简单的程序,用户可以在其中勾选不同颜色的复选框。如果勾选了几个框,那么它应该显示颜色的混合。勾选蓝色和黄色示例,然后标签显示绿色。 我有 3 个问题。

  1. 检查多种颜色不要像上面的例子那样混合。
  2. 取消选中复选框不会更改标签。
  3. 当所有这些都取消选中时,它应该返回到 "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);
        }
    }
}

你永远不会进入最后一种情况(蓝色和黄色),因为你处于 if-else 中,并且上述语句之一将被评估为 true before that (在这种情况下,只有蓝色的)。如果只有这四种情况,"blue and yellow" 应该放在第一个要检查的地方。

另一个选项:为每个选中的选项分配一个二进制位值,将三个复选框的值相加,然后 switch 得出该和:

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
}

正如我在评论中提到的,最好使用红色、绿色和蓝色,因为您处理的是加色,例如来自光束的颜色,而不是减色,例如来自油漆的颜色。如果您要处理减色,那么红色、黄色和蓝色是合适的,但同样,这不是这里的情况。

解决方案的另一种选择是使用枚举来表示您的颜色,如下所示:

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;
    }
}

然后我们可以通过 MyColor.values() 获取这些对象的数组,并使用它来创建 JCheckBoxes。如果我们把checkboxes放到一个集合中,比如一个Map,当一个状态改变时,我们可以检查所有checkboxes的状态:

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);
    }
}

GUI 可能如下所示:

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());
    }
}