joeyipod
joeyipod

Reputation: 79

ConcurrentModificationException issue

I'm trying to make a Brick Breaker game, but I'm getting a ConcurrentModificationException in this area.
I use Netbeans. This is in my BlockBreakerPanel class and it has the main information for getting my code to actually work properly. Exception location has ** around it.
I don't know why I get this exception and I'm wondering if it has to do with the Arraylist and if I somehow implemented it wrong.

public class BlockBreakerPanel extends JPanel implements KeyListener {

ArrayList<Block> blocks;
Block ball;
Block paddle;

JFrame mainFrame, startScreen;

Thread thread;

void reset() {
    blocks = new ArrayList<Block>();
    ball = new Block(237, 435, 35, 25, "ball.png");
    paddle = new Block(175, 480, 150, 25, "paddle.png");
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 0, 60, 25, "blue.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 25, 60, 25, "green.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 50, 60, 25, "yellow.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 75, 60, 25, "red.png"));
    }

    addKeyListener(this);
    setFocusable(true);
}

BlockBreakerPanel(JFrame frame, JFrame startScreen) {

    this.mainFrame = frame;
    this.startScreen = startScreen;

    reset();

    thread = new Thread(() -> {
        while (true) {
            update();
            try {
                Thread.sleep(10);
            } catch (InterruptedException err) {
                err.printStackTrace();
            }
        }
    });
    thread.start();

}
**public void paintComponent(Graphics g) {
    super.paintComponent(g);
    blocks.forEach(block -> {
        block.draw(g, this);
    });
    ball.draw(g, this);
    paddle.draw(g, this);
}**
public void update() {
    ball.x += ball.movX;
    
    if (ball.x > (getWidth() - 25) || ball.x < 0) {
        ball.movX *= -1;
    }

    if (ball.y < 0 || ball.intersects(paddle)) {
        ball.movY *= -1;
    }

    ball.y += ball.movY;

    if (ball.y > getHeight()) {
        thread = null;
        reset();
        mainFrame.setVisible(false);
        startScreen.setVisible(true);

    }
    blocks.forEach(block -> {
        if (ball.intersects(block) && !block.destroyed) {
            block.destroyed = true;
            ball.movY *= -1;
        }
    });
    repaint();

}

@Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyPressed(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_RIGHT && paddle.x < (getWidth() - paddle.width)) {
        paddle.x += 15;
    }

    if (e.getKeyCode() == KeyEvent.VK_LEFT && paddle.x > 0) {
        paddle.x -= 15;
    }

}

@Override
public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

}

}

Upvotes: 2

Views: 79

Answers (1)

jtahlborn
jtahlborn

Reputation: 53694

I suspect that the crux of your problem is that you are using a separate thread to interact with GUI elements. That is a no-no in Java, the AWT/Swing UI elements are not thread-safe. You must do all UI interactions on the event dispatch thread. Generally, this is very straightforward for normal interactive situations. In your case, however, you need a UI task to happen periodically. When you need a periodic update to UI elements in Java, you should use a swing timer. This will ensure that your updates happen in a UI thread-safe manner.

Upvotes: 1

Related Questions