javaactionjcolorchooser

Edit and update a running instance variable in a separate class


I am making a Simon Says style game, there are four colored squares and the computer does a sequence, then you copy that, etc. and am at a point where I want to add some more advanced features. The current feature I am looking at is looking to change the color panels actual colors at the users will and being able to change them individually from one another.

How can I get the 'color panel(s)' to change to a new color via JColorChooser while keeping everything else set up?

At the moment I have it split up into a few different classes and am having issues getting them all to communicate and just work properly.

Main class(Only a snippet):

public class Simonish implements ActionListener, MouseListener {

private ColorPanel colorPanel[] = new ColorPanel[4];
private ScorePanel scorePanel = new ScorePanel();
private Menu menuBar = new Menu();
private JPanel gameBoard = new JPanel();
private Random rand = new Random();
private ArrayList<ColorPanel> compSeq = new ArrayList<ColorPanel>();
private Iterator<ColorPanel> iter;
private JFrame frame = new JFrame();
private boolean playerTurn = false;
private int speed = 500;

public Simonish(Color[] colors){
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel pane = (JPanel)frame.getContentPane();
    pane.setLayout(new BorderLayout());

    gameBoard.setLayout(new GridLayout(2,2));
    gameBoard.setPreferredSize(new Dimension(400,400));

    for (int i=0;i<colorPanel.length;i++){
        colorPanel[i] = new ColorPanel(colors[i]);
        colorPanel[i].addMouseListener(this);
        gameBoard.add(colorPanel[i]);
    }

    scorePanel.addStartListener(this);

    frame.setJMenuBar(menuBar);
    pane.add(scorePanel, BorderLayout.NORTH);
    pane.add(gameBoard, BorderLayout.CENTER);

    frame.setLocationRelativeTo(null);
    frame.pack();
    frame.setVisible(true);

}

My Menu code (builds the menubar and implements the actions):

public class Menu extends JMenuBar {

private JMenuBar menuBar = new JMenuBar();

private JMenu settings = new JMenu("Settings");
private JMenu stats = new JMenu("Stats");
private JMenu help = new JMenu("Help");

private JMenuItem chooseColor = new JMenuItem(new ChooseColorAction("Choose Color"));
private JMenuItem colorMode = new JMenuItem(new ColorModeAction("Color Mode"));
private JMenuItem hScore = new JMenuItem("High Scores");
private JMenuItem history = new JMenuItem("History");
private JMenuItem about = new JMenuItem("About");
private JMenuItem rules = new JMenuItem("Rules");

public Menu(){
    this.add(settings);
    this.add(stats);
    this.add(help);

    settings.add(chooseColor);
    settings.add(colorMode);

    stats.add(hScore);
    stats.add(history);

    help.add(about);
    help.add(rules);
}
}

Action class to house the color changing code:

public class ColorModeAction extends AbstractAction {

public ColorModeAction(String name){
    super(name);
}

@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    Color[] colors = {Color.CYAN, Color.BLACK, Color.WHITE, Color.GREEN};
    //new Simonish(colors);
    //JOptionPane.showMessageDialog(null, "Color Mode");
}
}

Solution

  • Use interfaces to communicate your classes. For example; ColorModeAction needs to change colors so it should take an interface as parameter which able to change colors:

    public interface ColorChanger {
    
        public void changeColor(int index, Color newColor);
    } 
    

    Make Simonish implement that interface:

    public class Simonish implements ActionListener, MouseListener, ColorChanger  {
    
        public void changeColor(int index, Color new Color) {
            //Change the given panel's color
        }
    }
    

    Pass Simonish as parameter to the menu, and move new ColorModeAction("Color Mode") to the constructor. Then pass ColorChanger to the ColorModeAction as a parameter.

    public class Menu extends JMenuBar {
    
        ...
        private JMenuItem colorMode;
        ...
    
        public class Menu(ColorChanger colorChanger) {
             colorMode = new JMenuItem(new ColorModeAction(colorChanger, "Color Mode"));
        }
    }
    

    And the new ColorModeAction:

    public class ColorModeAction extends AbstractAction {
    
        private ColorChanger colorChanger;
    
        public ColorModeAction(ColorChanger colorChanger, String name) {
            super(name);
    
            this.colorChanger = colorChanger;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            Color[] colors = { Color.CYAN, Color.BLACK, Color.WHITE, Color.GREEN };
    
            colorChanger.changeColor(index, Color)
    
        }
    }
    

    It is not fully working code but I think you got the idea.