Search code examples
javaswingjpaneljbuttonactionlistener

When I press 1 button, I want all other buttons to change states


Right now with the code below, my output is 10 buttons with text/color. When I press a button, it uses the method ToggleState() to change its' text/color.

But when I press a button, I want all the OTHER buttons to use the method ToggleState(). So basically, I want the button pressed to stay in the same text/color, and all the other buttons to change text/color.

MyButton class:

public class MyButton extends JButton implements ActionListener {

private Color col1;
private Color col2;
private String text1;
private String text2;

public MyButton(Color col1, Color col2, String text1, String text2) {
    this.col1 = col1;
    this.col2 = col2;
    this.text1 = text1;
    this.text2 = text2;
    this.setText(text1);
    this.setBackground(col1);
    this.setOpaque(true);
    this.addActionListener(this);
}

public void ToggleState() {
    Color initialBackground = this.getBackground();

    if (initialBackground == col1) {
        this.setBackground(col2);
        this.setText(text2);
    } else if (initialBackground == col2) {
        this.setBackground(col1);
        this.setText(text1);
    }
}

public void actionPerformed(ActionEvent e) {
    if (e.getSource() == this) {
        this.ToggleState();
    }
}
}

CMain class:

public class CMain{

private static JPanel panel = new JPanel();

public static void main(String[] args) {

    Random randomGenerator = new Random();

    JFrame frame = new JFrame("MyButton testing");

    for (int i = 0; i < 10; i++) {

        float r = randomGenerator.nextFloat();float g = randomGenerator.nextFloat();float b = randomGenerator.nextFloat();float r2 = randomGenerator.nextFloat();float g2 = randomGenerator.nextFloat();float b2 = randomGenerator.nextFloat();

        String theText = "button nr: " + i;
        String theOtherText = "SWITCH ME";
        Color theColor = new Color(r, g, b);
        Color theOtherColor = new Color(r2, g2, b2);

        MyButton myb = new MyButton(theColor, theOtherColor, theText, theOtherText);
        panel.add(myb);
    }
    frame.add(panel);
    frame.pack();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

I have thought about a few solutions, for example putting in a new actionlistener in the CMain class, this is the code I wrote for that:

public void actionPerformed(ActionEvent e) {
    if (e.getSource() == this) {
        for (int j=0 ; j < panel.getComponentCount() ; j++) {
            ((CMain)panel.getComponent(j)).ToggleState();
        }
    }
}

But it doesn't solve my problem, I have the exact same output as before. When I press 1 button, only that button gets switched. I understand that the code above would ToggleState() all my buttons (and not only the ones that I haven't pressed), I just wanted to try something out.

Maybe I could save all my buttons in a list when I create them in CMain class, and then create a new ToggleState() in CMain that toggles every button not pressed in the list, but I have no idea how a solution like that would look in code.

EDIT: I tried (after a tip in comment section) removing actionListener from my MyButton class and put it in CMain class, the problem is, that it switches ALL of my buttons, including the one that I pressed. I'm closer now, but I still need the button I've pressed to remain the same:

ArrayList<MyButton> knappar = new ArrayList<MyButton>();
MyButton myb = new MyButton(theColor, theOtherColor, theText, theOtherText);
knappar.add(myb);
panel.add(myb);

myb.addActionListener(new ActionListener() {    
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == knappar);
            for (int k=0; k<knappar.size();k++) {
            knappar.get(k).ToggleState();
            }
    }
});

Solution

  • lost with the if statement, not sure how I should set it up.

    The if statement needs to be inside the loop.

    for (int k=0; k<knappar.size();k++)
    {
        MyButton button = knappar.get(k);
    
        if (button != e.getSource())
            button.toggleState();
    }
    

    Also, note how I renamed the method. Method names should NOT start with an upper case character.

    Or you use the following looping syntax:

    for (MyButton button: knapper)
    {
        if (button != e.getSource())
            button.toggleState();
    }