0

I am learning Java on my own and having some issues with graphics. I learned a lot from StackOverflow! I would have posted a lot earlier had it not been for earlier threads!

Here is the basic scenario. I have JFrame on which I am added Balls (which is another class extending JPanel). The balls move randomly and one ball moves on a rectangle. There are three buttons on panel: Pause, Add Random Ball, and Remove Random Ball. I am having issues with removing balls. It gives exception of concurrent access to an ArrayList and I am not sure how to go around that.

And also I would like to turn pause button into pause/play but not sure how to restart the run method as its not static method.

Since I am new to Java I may be doing some basic mistakes or my approach may not be correct. Any suggestions will be appreciated. Thanks !

Here is the code:

Ball Class

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class Balls extends JPanel {

    public static ArrayList<Balls> BallList = new ArrayList<Balls>();

    public Balls(String n, Color col, String nm) {
        mode = n;
        ballcolor = col;
        name = nm;
        if (name != "dummy") {
            BallList.add(this);
        }

    }

    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponent(g);

        for (Balls ball : BallList) {
            g.setColor(ball.ballcolor);
            g.fillOval(ball.x, ball.y, 20, 20);
        }

    }

    private int x, y;
    private String name;
    private static Boolean run = true;
    public String mode;
    public Color ballcolor;
    private String DirectionR = "R";

    private void getposition() {

        if (mode.equals("Circle")) {
        }

        if (mode.equals("Rectangle")) {
            if (x == 0) {
                x = 150;
            }

            if (y == 0) {
                y = 200;

            }

            if (x == 150 && y == 200) {
                DirectionR = "R";

            }

            if (x == 350 && y == 200) {
                DirectionR = "D";

            }

            if (x == 350 && y == 300) {
                DirectionR = "L";

            }

            if (x == 150 && y == 300) {
                DirectionR = "U";

            }

            if (DirectionR.equals("R")) {
                x++;
            }

            if (DirectionR.equals("L")) {
                x--;
            }

            if (DirectionR.equals("U")) {
                y--;
            }

            if (DirectionR.equals("D")) {
                y++;
            }

        }

        if (mode.equals("Random")) {
            x = (int) (Math.random() * 400);
            y = (int) (Math.random() * 400);
        }

    }

    public void run() {

        while (run == true) {

            for (Balls ball : BallList) {
                ball.getposition();
            }

            try {
                Thread.sleep(20);
            } catch (InterruptedException e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }
            repaint();
        }

    }

    static class pauseframe implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            if (run.equals(true)) {
                run = false;
            }

            else {
                run = true;
            }
        }
    }

    static class addball implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            Balls Randn = new Balls("Random", Color.GREEN, "NEW ADDED");
            for (Balls ball : BallList) {
                System.out.println(ball.name);
            }
        }
    }

    static class Delball implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub

            for (Balls ball : BallList) {
                System.out.println(ball.mode);
                if (ball.mode.equals("Random")) {
                    BallList.remove(ball);
                }

            }
        }
    }
}

Tester Class

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Balls_test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JFrame frame = new JFrame();
        Balls dummy = new Balls("Dummy", Color.BLACK, "dummy");
        frame.setSize(500, 500);
        frame.getContentPane().add(dummy);
        frame.setBackground(Color.WHITE);
        dummy.setBackground(Color.WHITE);

        Balls Rect = new Balls("Rectangle", Color.RED, "Rect");

        Balls Rand = new Balls("Random", Color.BLUE, "Rand");

        Button pause = new Button("Pause");
        ActionListener pauseall = new Balls.pauseframe();
        pause.addActionListener(pauseall);
        frame.getContentPane().add(BorderLayout.NORTH, pause);

        Button addRandom = new Button("Add Random Ball");
        ActionListener NewBall = new Balls.addball();
        addRandom.addActionListener(NewBall);
        frame.getContentPane().add(BorderLayout.SOUTH, addRandom);

        Button DelRandom = new Button("Remove Random Ball");
        ActionListener DelBall = new Balls.Delball();
        DelRandom.addActionListener(DelBall);
        frame.getContentPane().add(BorderLayout.WEST, DelRandom);

        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        dummy.run();

    }

}
David Yee
  • 3,515
  • 25
  • 45
NewGuyInJava
  • 218
  • 2
  • 13
  • 2
    Follow Java naming conventions. Variable names should NOT start with upper case characters. Some of your names area correct and some are not! Be consistent! – camickr Jun 03 '14 at 21:02

2 Answers2

1

You can't remove the item while iterating the List as used in your code:

public static ArrayList<Balls> BallList = new ArrayList<Balls>();

for (Balls ball : BallList) {
    System.out.println(ball.mode);
    if (ball.mode.equals("Random")) {
         BallList.remove(ball); 
    }
}

You should use Iterator to remove the item while iterating the List as well.

Sample code:

Iterator<Balls> it = BallList.iterator();

while(it.hasNext()) {
    Balls ball = it.next();
    System.out.println(ball.mode);
    if (ball.mode.equals("Random")) {
        it.remove();
    }
}
Braj
  • 46,415
  • 5
  • 60
  • 76
1
  1. Your add action never adds the ball to the ball list, so there are no "Random" balls in the list
  2. if (name != "dummy") { is not how String comparison works in Java
  3. You can't remove an element from a List while it's been iterated. You could use a synchronized block to ensure that only one thread is accessing the List at a time, but it might be easier to use an Iterator to iterate over the List instead
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks MadProgrammer.. I fixed the code by getting the index of "Random" ball, breaking from loop and then removing it after the loop. That fixed the issue. iterator sounds good too. Fixed the String Comparison too. on and btw I was adding random ball when the main method is executed so random ball will be there when I click on random ball removal button. – NewGuyInJava Jun 04 '14 at 18:17