Why is my method not clearing the ArrayList?

actionlistener, arraylist, java, user-interface

Solution

I see two immediate issues.

The first is, you're calling `addRect` within the `paintComponent` method, which means, even after you clear the `List`, on the next repaint, a new rectangle will be added to it.

Secondly, I would call `repaint` in the `DrawPanel` instead of using `frame.repaint()`, as you really only want to update the draw panel, not the entire frame

public class BadPaint05 {

    public static void main(String[] args) {
        new BadPaint05();
    }

    public BadPaint05() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MasterPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MasterPane extends JPanel {

        private DrawPanel drawPane;
        private Timer timer;

        public MasterPane() {
            setLayout(new BorderLayout());
            drawPane = new DrawPanel();

            add(drawPane);

            JButton stop = new JButton("Stop");
            stop.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    drawPane.clearEvent(e);
                    timer.stop();
                }
            });

            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    drawPane.addRect();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();

            add(stop, BorderLayout.SOUTH);

        }

    }

    class DrawPanel extends JPanel {

        ArrayList<MyRectangle> rects = new ArrayList<>();
        Random rand = new Random();

        @Override
        public void paintComponent(Graphics g) {

            super.paintComponent(g);

//            addRect();

            for (MyRectangle r : rects) {
                g.setColor(r.getColor());
                g.fillRect(r.x, r.y, r.width, r.height);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

        public ArrayList<MyRectangle> addRect() {
            int ht = rand.nextInt(getHeight());
            int wd = rand.nextInt(getWidth());

            int x = rand.nextInt(getWidth() - wd);
            int y = rand.nextInt(getHeight() - ht);

            int r = rand.nextInt(256);
            int g = rand.nextInt(256);
            int b = rand.nextInt(256);

            rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g)));
            System.out.println(rects.size());
            repaint();
            return rects;
        }

        public void clearEvent(ActionEvent e) {
            System.out.println(rects.size());
            rects.clear();
//            frame.repaint();
            repaint();
            System.out.println("I was called");
        }
    }

    public class MyRectangle {

        private int x, y, width, height;
        private Color color;

        private MyRectangle(int x, int y, int wd, int ht, Color color) {
            this.x = x;
            this.y = y;
            this.width = wd;
            this.height = ht;
            this.color = color;
        }

        public Color getColor() {
            return color;
        }

    }
}

Problem

NOTE: The problem with my code was simply that I created the method to clear the rects and everything but the only thing I was doing wrong was instantiating DrawPanel class's myDraw object inside of the go() method. And so I had to instantiate DrawPanel again with Stop and that created a whole new object. So I ended up calling the clearRects method on a different DrawPanel object than the one rects were being added to. Anyway, I decided to go with code suggestions by MadProgrammer because his code was exactly how Java: A Beginner's Guide teaches it and was much cleaner. Well, I have been running around StackOverflow since this morning and have been able to fix a lot of problems with my code but I am still stuck with this problem with ArrayLists. I have the following piece of code that does not seem to do what I intend for it to do. Now I am aware that I am the one making a mistake somewhere but not really sure how to correct it. The way it is set up is that when I hit the stop button, the ArrayList should clear so I have a blank JPanel so to speak, here's the code snippets. I can post the whole program if you want me to though but I am only pasting the snippet here because I'm assuming I'm making a pretty simple and dumb mistake on my part: ``` class DrawPanel extends JPanel { ArrayList<MyRectangle> rects = new ArrayList<>(); Random rand = new Random(); @Override public void paintComponent(Graphics g) { super.paintComponent(g); addRect(); for(MyRectangle r : rects) { g.setColor(r.getColor()); g.fillRect(r.x, r.y, r.width, r.height); } } @Override public Dimension getPreferredSize() { return new Dimension(500,500); } public ArrayList<MyRectangle> addRect() { int ht = rand.nextInt(getHeight()); int wd = rand.nextInt(getWidth()); int x = rand.nextInt(getWidth() - wd); int y = rand.nextInt(getHeight() - ht); int r = rand.nextInt(256); int g = rand.nextInt(256); int b = rand.nextInt(256); rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g))); System.out.println(rects.size()); return rects; } public void clearEvent(ActionEvent e) { System.out.println(rects.size()); rects.clear(); frame.repaint(); System.out.println("I was called"); } } ``` And here's the part where the button calls it in its actionPerformed method: ``` class StopListener implements ActionListener { DrawPanel draw = new DrawPanel(); public void actionPerformed(ActionEvent e) { timer.stop(); draw.clearEvent(e); } } ``` EDIT: I understand that the arraylist object that my clearEvent method refers to is not the same one that addRect()'s adding stuff to. What I am asking, I guess, is how to make it "connect" so I can wipe things clean using the JButton. EDIT: Here's the full program: ``` import javax.swing.*; import java.awt.event.*; import java.util.ArrayList; import java.util.Random; import java.awt.*; public class TwoButtonsRandomRec { JFrame frame; Timer timer; public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { TwoButtonsRandomRec test = new TwoButtonsRandomRec(); test.go(); } }); } public void go() { frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton startButton = new JButton("Start"); startButton.addActionListener(new StartListener()); JButton stopButton = new JButton("Stop"); stopButton.addActionListener(new StopListener()); final DrawPanel myDraw = new DrawPanel(); timer = new Timer(50, new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { myDraw.repaint(); } }); frame.add(startButton, BorderLayout.NORTH); frame.add(stopButton, BorderLayout.SOUTH); frame.add(myDraw, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } class StartListener implements ActionListener { public void actionPerformed(ActionEvent e) { timer.start(); } } class StopListener implements ActionListener { DrawPanel draw = new DrawPanel(); public void actionPerformed(ActionEvent e) { timer.stop(); draw.clearEvent(e); } } class DrawPanel extends JPanel { ArrayList<MyRectangle> rects = new ArrayList<>(); Random rand = new Random(); @Override public void paintComponent(Graphics g) { super.paintComponent(g); addRect(); for(MyRectangle r : rects) { g.setColor(r.getColor()); g.fillRect(r.x, r.y, r.width, r.height); } } @Override public Dimension getPreferredSize() { return new Dimension(500,500); } public ArrayList<MyRectangle> addRect() { int ht = rand.nextInt(getHeight()); int wd = rand.nextInt(getWidth()); int x = rand.nextInt(getWidth() - wd); int y = rand.nextInt(getHeight() - ht); int r = rand.nextInt(256); int g = rand.nextInt(256); int b = rand.nextInt(256); rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g))); System.out.println(rects.size()); return rects; } public void clearEvent(ActionEvent e) { System.out.println(rects.size()); rects.clear(); repaint(); System.out.println("I was called"); } } } class MyRectangle extends Rectangle { Color color; public MyRectangle(int x, int y, int w, int h, Color c) { super(x, y, w, h); this.color = c; } public Color getColor() { return color; } } ``` Here's the previous relevant question I asked here in case anyone's interested. Strange JFrame Behavior

Original source