#java #exception
#java #исключение
Вопрос:
Я пытаюсь создать игру для взлома кирпичей, но я получаю ConcurrentModificationException
в этой области.
Я использую Netbeans. Это в моем BlockBreakerPanel
классе, и в нем содержится основная информация для того, чтобы мой код действительно работал должным образом. Местоположение исключения имеет ** вокруг него.
Я не знаю, почему я получаю это исключение, и мне интересно, связано ли это с Arraylist
и если я как-то неправильно его реализовал.
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) amp;amp; !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 amp;amp; paddle.x < (getWidth() - paddle.width)) {
paddle.x = 15;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT amp;amp; paddle.x > 0) {
paddle.x -= 15;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Комментарии:
1. Что такое
blocks
и где вы его обновляете?2.
blocks
это созданный мной arraylist, содержащий различные изображения PNG, которые образуют блоки.blocks = new ArrayList<Block>();
3. Нет, к сожалению, это не @luk2302. Я бы хотел, чтобы это произошло. Мне нужно исправить код и как он должен выглядеть по сравнению с тем, что у меня есть.
4. из какой строки кода исходит исключение? что такое полная трассировка стека?
5. Да, он отвечает на вопрос в том смысле, что он описывает, что такое исключение, почему оно возникает и как его предотвратить.
Ответ №1:
Я подозреваю, что суть вашей проблемы в том, что вы используете отдельный поток для взаимодействия с элементами графического интерфейса. Это недопустимо в Java, элементы пользовательского интерфейса AWT / Swing не являются потокобезопасными. Вы должны выполнять все взаимодействия с пользовательским интерфейсом в потоке отправки событий. Как правило, это очень просто для обычных интерактивных ситуаций. Однако в вашем случае вам необходимо, чтобы задача пользовательского интерфейса выполнялась периодически. Когда вам требуется периодическое обновление элементов пользовательского интерфейса в Java, вы должны использовать таймер swing. Это гарантирует, что ваши обновления будут выполняться потокобезопасным способом пользовательского интерфейса.
Комментарии:
1. Итак, какие изменения мне нужно внести в код в этом классе специально для его работы? Что мне нужно добавить в какие конкретные методы?
2. @joey ты прочитал все ссылки, которые я предоставил? вам нужно прекратить использование потока и начать использовать таймер переключения