Search code examples
javafor-loopif-statementactionlistenerjtogglebutton

Changing color of a button depending on state of some Array elements


I am trying to program a JToggleButton Listener for my GUI. The JToggleButtons with this Listener basicly expand the UI to show more Elements and can close them again which all works like expected. However some of the hidden elements are JTextAreas, which depending on if they are filled or not should give the corresponding JToggleButton a different color. I want to make the button red if none of the JTextAreas are filled, yellow if some but not all are filled and finally green if every JTextArea has some text in it. Previously I had custom Listeners for every button, which worked but was horrible to maintain.

Now my code looks like this:

    ActionListener ExpandListener = new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        JToggleButton button = (JToggleButton) e.getSource();
        i = (int) button.getClientProperty("number");
        y=0;
        for(int f=0;f<i;f++){
            y += ChapterSize[f];
        }
        if(ExpandButtons[i].isSelected()){
           for(int g=0;g<ChapterSize[i];g++){
           Comments[g+y].setVisible(true);
           }
        }else{
           for(int g=0;g<ChapterSize[i];g++){
           Comments[g+y].setVisible(false);
           }
        Boolean GreenFlag = false;
        Boolean YellowFlag = false;
        Boolean RedFlag = false;
        for(int g=0;g<ChapterSize[i];g++){
                if(!Comments[g+y].getText().isEmpty()){
                    GreenFlag = true;
                    YellowFlag = true;
                }else{
                    GreenFlag = false;
                }
                if(Comments[g+y].getText().isEmpty()){
                    RedFlag = true;
                }else{
                    RedFlag = false;
                }
            }
            if(GreenFlag == true){
                ExpandButtons[i].setBackground(Color.GREEN);
                YellowFlag = false;
            }
            if(RedFlag == true)ExpandButtons[i].setBackground(Color.RED);
            if(YellowFlag == true)ExpandButtons[i].setBackground(Color.YELLOW);
            }
          }
        };

It kind of works, but I have some issues. Since I don't know how to put an AND or OR Statement of variable length in the loop for the ColorFlags, only the last JTextArea that gets checked is really relevant for the state of the Booleans. So the Button will stay green even if there are empty TextAreas, as long as its not the last one or all of them.

I hope I'm just thinking into the wrong direction and that there is an easier way to write what I want, but despite hours of searching online I haven't been able to find a solution.


Solution

  • I'm not clear yet on what exact behavior you're trying to elicit. What I do know is that

    • Yes, your code is quite convoluted, difficult for us to follow, and likely can be and should be simplified. One way....
    • If you're trying to have your button color change based on the text state of the JTextAreas then the JTextAreas themselves should have DocumentListeners attached to their Documents, and that you should probably change the state of the buttons colors from these listeners, not from the button's action listeners.
    • Side issue: I usually use an ItemListener with toggling buttons such as JToggleButton, JCheckBox or JRadioButton, if I want to respond to changes in their selection state.

    For example:

    import java.awt.Color;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.*;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.JTextComponent;
    
    @SuppressWarnings("serial")
    public class JToggleTest extends JPanel {
        private static final int AL_COUNT = 5;
        private JToggleButton toggleButton = new JToggleButton("Toggle Button");
        private List<JTextComponent> textComps = new ArrayList<>();
    
        public JToggleTest() {
            add(toggleButton);
            for (int i = 0; i < AL_COUNT; i++) {
                JTextArea textArea = new JTextArea(3, 15);
                textArea.getDocument().addDocumentListener(new MyDocListener());
                add(new JScrollPane(textArea));
                textComps.add(textArea);
            }
            toggleButton.setBackground(Color.RED);
        }
    
        private class MyDocListener implements DocumentListener {
    
            @Override
            public void changedUpdate(DocumentEvent e) {
                checkDocs();
            }
    
            @Override
            public void insertUpdate(DocumentEvent e) {
                checkDocs();
            }
    
            @Override
            public void removeUpdate(DocumentEvent e) {
                checkDocs();
            }
    
            private void checkDocs() {
                int count = 0;
                for (JTextComponent textComp : textComps) {
                    if (!textComp.getText().trim().isEmpty()) {
                        count++;
                    }
                }
                System.out.println("count: " + count);
                switch (count) {
                case 0:
                    toggleButton.setBackground(Color.RED);
                    break;
    
                case AL_COUNT:
                    toggleButton.setBackground(Color.GREEN);
                    break;
    
                default:
                    toggleButton.setBackground(Color.YELLOW);
                    break;
                }
            }
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("JToggleTest");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new JToggleTest());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }