1

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.

Lotec
  • 37
  • 6
  • Write a method that accepts a "comment" and returns a desired color. After that, you'll have much easier time completing the rest. In general, try to write methods so short that their correctness is painfully obvious. Also, please don't name fields and variables with `InitalCapitals`, this is normally reserved for class names; use `lowerCamelCase` for variables. This helps other people read the source. – 9000 Sep 20 '17 at 16:51

1 Answers1

2

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());
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    Side issue 2: rather than having "...despite hours of searching online I haven't been able to find a solution....", much better to show concrete results of what you *have* found online. Gear your question towards including information that will help us answer it. – Hovercraft Full Of Eels Sep 20 '17 at 16:44
  • First of all, thank you for the quick respone. The JTextAreas already have DocumentListeners to change their Borders, so that probably seems like a good place to start. I also never knew about ItemListeners so thank you for pointing that out. – Lotec Sep 20 '17 at 16:51
  • Mostly I had difficulty just to find something relevant to my problem. I don't have much experience in Java, so sometimes I just don't really know what to search for. But again, I only want to change the color of some ToggleButtons depending on the state of the JTextAreas it contains. – Lotec Sep 20 '17 at 16:58
  • @Lotec: see example of the doc listener – Hovercraft Full Of Eels Sep 20 '17 at 17:01
  • Just wrote a very similar solution that works. Thank you for your help! This really is a lot easier than my convoluted ActionListener :) – Lotec Sep 20 '17 at 17:15