2016-11-27 3 views
0

поэтому у меня есть эта маленькая змейка, и я получаю ошибку StackOverflow, которая выглядит так:Java StackOverflowException в GUI

Exception in thread "main" java.lang.StackOverflowError 
at java.awt.Component.setBackground(Component.java:1835) 
at javax.swing.JComponent.setBackground(JComponent.java:2733) 
at javax.swing.LookAndFeel.installColors(LookAndFeel.java:175) 
at javax.swing.LookAndFeel.installColorsAndFont(LookAndFeel.java:211) 
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(BasicPanelUI.java:66) 
at javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:56) 
at javax.swing.JComponent.setUI(JComponent.java:666) 
at javax.swing.JPanel.setUI(JPanel.java:153) 
at javax.swing.JPanel.updateUI(JPanel.java:126) 
at javax.swing.JPanel.<init>(JPanel.java:86) 
at javax.swing.JPanel.<init>(JPanel.java:109) 
at javax.swing.JPanel.<init>(JPanel.java:117) 
at SnakeGame.Animation.<init>(Animation.java:36) 
at SnakeGame.Snake.<init>(Snake.java:24) 
at SnakeGame.Animation.<init>(Animation.java:38) 
at SnakeGame.Snake.<init>(Snake.java:24) 

Я знаю, что есть некоторая бесконечная рекурсия происходит, но я не получить его. Кажется, это просто конструктор. так вот код для анимации класса:

//imports are there 
interface Drawable{ 
public void draw(Graphics g); 
} 


public class Animation extends JPanel implements ActionListener, KeyListener{ 

JFrame frame; 
List <Drawable> toDraw; 
Snake snake; 
Food food; 
Timer timer; 

public static boolean gameOver = false; 
public static int UNIT = 20; 
public static int SIZE = 500; 


public static void main(String[] args){ 
    Animation animate = new Animation(); 
    animate.setUpFrame(); 
} 

Animation(){ 

    toDraw = new ArrayList<>(); // this is line 38 from exception 
    snake = new Snake(SIZE/2,SIZE/2); 
    food = new Food(); 
    toDraw.add(snake); 
    toDraw.add(food); 
    initTimer(); 
} 

void initTimer(){ 
    timer = new Timer(200, this); 
    timer.setInitialDelay(1000); 
    timer.start(); 
} 

void setUpFrame(){ 
    frame = new JFrame("Snake"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(SIZE, SIZE); 
    frame.setFocusable(true); 
    frame.setVisible(true); 
    frame.add(this); 
} 

void gameRun() { 
     //haven't written here anything yet. 
} 

    @Override 
public void paintComponent(Graphics g){ 
    super.paintComponent(g); 
    this.setBackground(new Color(70,130,80)); 

    for(Drawable d : toDraw){ 
     d.draw(g); 
    } 

} 

@Override 
public void actionPerformed(ActionEvent e) { 
     gameRun(); 
     repaint(); 
} 


@Override 
public void keyTyped(KeyEvent e) { 

} 

@Override 
public void keyPressed(KeyEvent e) { 
    int c = e.getKeyCode(); 
    switch(c){ 
     case 'L': 
      snake.setDirection('L'); 
      break; 
     case 'R': 
      snake.setDirection('R');   
      break; 
     case 'U': 
      snake.setDirection('U'); 
      break; 
     case 'D': 
      snake.setDirection('D'); 
      break; 
    } 
} 

@Override 
public void keyReleased(KeyEvent e) { 

} 

} 

А вот класс змея:

public class Snake extends Animation implements Drawable { 

int x; 
int y; 
char direction = 'N'; 

Snake(int x, int y){ //line 24 from exception 
    this.x = x; 
    this.y = y; 
} 


void setDirection(char way){ 
    direction = way; 
} 
void move(char direction){ 

    if(x < 0){ 
     x = SIZE; 
    } 
    else if(x > SIZE){ 
     x = 0; 
    } 
    if(y < 0){ 
     y= SIZE; 
    }else if (y > SIZE){ 
     y = 0; 
    } 

    switch(direction){ 
     case 'L': 
      x-= UNIT; 
      break; 
     case 'R': 
      x+= UNIT;    
      break; 
     case 'U': 
      y-= UNIT;  
      break; 
     case 'D': 
      y+= UNIT; 
      break; 
    } 
} 

@Override 
public void draw(Graphics g) { 
    g.setColor(new Color(160,2,42)); 
    g.fill3DRect(x, y, UNIT, UNIT, true); 
    } 
} 

Любая помощь будет принята с благодарностью!

+0

Ваше наследство не имеет смысла, почему 'Snake' продлевает« Анимацию »в любом случае? – Li357

+0

@AndrewLi Спасибо! Наследование - мое слабое место. Я думаю, что я просто создаю абстрактный класс для любого физического объекта и от него. –

ответ

2

У вас есть непреднамеренное рекурсию из-за структуры наследования вашей программы:

змея расширяет Animation , который создает Змею в своем конструкторе, который проходит анимацию , который создает Змею в своем конструкторе, который расширяет Animation который создает Змею в своем конструкторе, который расширяет анимацию , которая создает Змею в своем конструкторе, которая расширяет анимацию , которая создает Змею в ее конструкторе ... и т. д.

Решение: у вас нет змеиной анимации. И это также логично, так как ваш Змей не действует как компонент Swing, такой как JPanel, и поэтому не должен наследовать от JPanel. Скорее это логическая сущность, которая нарисована JPanel, и поэтому вы хотите использовать композицию здесь (которую вы уже делаете) и не наследование (чего вы, к сожалению, тоже делаете).

+0

Спасибо! Я не знаю, как наследование работает очень хорошо, так как я читал об этом в то время, когда я не мог ничего сделать в java. Мне нужно освежить свои знания. –