2015-06-09 6 views
2

Когда я пытаюсь контролировать свой характер с помощью клавиш со стрелками, все работает нормально, но через некоторое время я получаю эту ошибку:Stackoverflow ошибка с ActionListeners

Exception in thread "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

Пожалуйста, пост полный трассировки стека. Укажите, какая строка кода виновата. Вероятно, у вас есть рекурсия, и вы должны помочь нам найти ее, опубликовав полный вопрос. –

+0

Трассировка стека - это просто «Исключение в потоке» AWT-EventQueue-0 «java.lang.StackOverflowError« раз и навсегда »в java.awt.AWTEventMulticaster.keyPressed (AWTEventMulticaster.java:249)« повторяется много раз. – Priyank

+0

В будущем опубликуйте полную стекцию, как с вашим вопросом, а не в комментарии, так как это слишком важно, чтобы похоронить в комментарии. Но теперь не важно, поскольку я знаю вашу проблему - вы повторно добавляете KeyListener в код while (true) 'loop - опасный код. Вы только хотите добавить KeyListener один раз и на самом деле не хотите использовать его вообще, поскольку даже Oracle рекомендует избегать использования этого в пользу Key Bindings. –

ответ

3

Ваша текущая петля стреляет вам в ногу, когда вы добавляете KeyListener тысячу раз в этом цикле. Не делайте этого, в частности, ваш метод renderGame(). Почему вы даже хотите вызвать метод, который многократно устанавливает GUI? Было бы разумнее назвать этот метод один раз.

Кроме того, вместо тайм-аута используйте таймер Swing Timer (Google учебник), избегайте KeyListeners в пользу Key Binding (Google учебник, и посмотрите на this example) и сделайте только свой установочный код один раз.

Кроме того, ваш код подвержен риску возникновения ошибок при навивке Swing, поскольку вы вызываете Thread.sleep(...) и while (true) в нефонической теме. Для безопасности используйте вместо этого таймер Swing.

Кроме того, вы сравниваете строки неправильно. Не сравнивайте строки с использованием == или !=. Вместо этого используйте метод equals(...) или equalsIgnoreCase(...). Поймите, что == проверяет, соответствуют ли ссылки объектам. Эти методы, с другой стороны, проверяют, имеют ли две строки одинаковые символы в одном порядке, и это имеет значение здесь. Таким образом, вместо

if (fu == "bar") { 
    // do something 
} 

сделать,

if ("bar".equals(fu)) { 
    // do something 
} 

или,

if ("bar".equalsIgnoreCase(fu)) { 
    // do something 
}