Reputation: 147
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.
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);
}
}
}
Upvotes: 0
Views: 1096
Reputation: 285430
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());
}
}
Upvotes: 0
Reputation: 4592
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
}
Upvotes: 2
Reputation: 6123
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.
Upvotes: 5