当我尝试用箭头键控制我的角色时,一切正常,但过了一段时间后我得到了这个错误:
线程中的异常" AWT-EventQueue-0" java.lang.StackOverflowError的
然后
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:249)
多次。我所拥有的课程甚至不是249行代码,所以我不知道在哪里寻找问题。我的代码现在非常混乱,但是如果它能帮助任何人提出答案,我会发布它。
import javax.swing.JButton;
import javax.swing.JComponent;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.image.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class mainFrame extends JPanel implements Runnable, KeyListener {
static boolean gameIsRunning = false;
static final int TARGET_FPS = 1;
static int x = 100;
static int y = 100;
static long startTime = 0;
static long elapsedTime = 0;
static long waitTime = 0;
JFrame window = new JFrame("Out from Eden");
JPanel panel = new JPanel();
getResources get = new getResources();
BufferedImage player = get.getImg("player");
static int playerVal = 0;
static int i = 0;
static String currentState = "";
static int lastFacing = 0;
public void createFrame() {
gameIsRunning = true;
gameStart();
}
public void setGame(boolean game) {
gameIsRunning = game;
}
public void gameStart() {
(new Thread(new mainFrame())).start();
}
public void run() {
while (gameIsRunning == true) {
startTime = System.nanoTime();
updateGame();
renderGame();
elapsedTime = System.nanoTime() - startTime;
waitTime = (TARGET_FPS * 10) - (elapsedTime / 1000000);
if (waitTime < 0) {
waitTime = 5;
}
try {
Thread.sleep(waitTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateGame() {
if (x > 800) {
x = 0;
}
if (currentState == "left") {
x--;
}
if (currentState == "right") {
x++;
}
player = royImage();
}
public BufferedImage royImage() {
if (currentState == "right") {
lastFacing = 2;
i++;
if (playerVal == 0) {
playerVal = 1;
i = 0;
player = get.getImg("royWalk1");
}
if (playerVal == 1 && i > 20) {
playerVal = 2;
i = 0;
return get.getImg("royWalk2");
}
if (playerVal == 2 && i > 20) {
playerVal = 3;
i = 0;
player = get.getImg("royWalk3");
}
if (playerVal == 3 && i > 20) {
playerVal = 4;
i = 0;
player = get.getImg("royWalk4");
}
if (playerVal == 4 && i > 20) {
playerVal = 0;
i = 0;
player = get.getImg("royWalk1");
}
}
if (currentState == "left") {
lastFacing = 1;
i++;
if (playerVal == 0) {
playerVal = 1;
i = 0;
player = get.getImg("royWalkL1");
}
if (playerVal == 1 && i > 20) {
playerVal = 2;
i = 0;
player = get.getImg("royWalkL2");
}
if (playerVal == 2 && i > 20) {
playerVal = 3;
i = 0;
player = get.getImg("royWalkL3");
}
if (playerVal == 3 && i > 20) {
playerVal = 4;
i = 0;
player = get.getImg("royWalkL4");
}
if (playerVal == 4 && i > 20) {
playerVal = 0;
i = 0;
player = get.getImg("royWalkL1");
}
}
if (currentState == "null") {
i = 0;
playerVal = 0;
if (lastFacing == 1) {
player = get.getImg("playerL");
}
if (lastFacing == 2) {
player = get.getImg("player");
}
}
return player;
}
public void renderGame() {
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 700, 500);
panel.setLayout(new BorderLayout());
window.getContentPane().add(panel);
panel.add(this);
window.setFocusable(true);
window.setFocusTraversalKeysEnabled(false);
window.setVisible(true);
window.addKeyListener(this);
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawString("Hello", x, y);
g2.drawLine(0, 63, 700, 63);
g2.drawImage(player, x - 100, y - 100, null);
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
currentState = "up";
}
if (code == KeyEvent.VK_DOWN) {
currentState = "down";
}
if (code == KeyEvent.VK_LEFT) {
currentState = "left";
}
if (code == KeyEvent.VK_RIGHT) {
currentState = "right";
}
}
public void keyReleased(KeyEvent e) {
currentState = "null";
}
}
任何人都可以帮我弄清楚为什么我会收到堆栈溢出错误以及如何避免它?
答案 0 :(得分:3)
当你在该循环中添加一千次KeyListener时,你真正的循环就是在你脚下射击。不要这样做,特别是你的renderGame()
方法。为什么你甚至想要多次调用一个用于设置GUI的方法?调用该方法一次会更有意义。
另外,使用Swing Timer(Google教程)代替你的while循环,避免KeyListeners支持Key Binding(谷歌本教程,看看this example)并做你的设置 - 代码只有一次。
此外,当您在非后台线程中调用Thread.sleep(...)
和while (true)
时,您的代码可能会导致Swing线程错误。为安全起见,请改用Swing Timer。
另外,你比较错误的字符串。不要使用==
或!=
比较字符串。请改用equals(...)
或equalsIgnoreCase(...)
方法。了解==
检查两个对象引用是否相同而不是您感兴趣的内容。另一方面,这些方法检查两个字符串是否具有相同的字符以相同的顺序,这是重要的。而不是
if (fu == "bar") {
// do something
}
做,
if ("bar".equals(fu)) {
// do something
}
,或者
if ("bar".equalsIgnoreCase(fu)) {
// do something
}