2016-03-17 2 views
0

Я пытаюсь сделать игру жизни Конвея, но у меня проблемы с использованием метода repaint(). Я создал класс, который расширяет JPanel, и я звоню super.paint(g), когда я переопределяю краску, плюс я не переопределяю метод repaint(), но мне не повезло. Основной метод, который я проверить это в это здесь (пожалуйста, простите мои ужасные идентификаторы):Проблемы с компонентом/JPanel repaint()

import javax.swing.JFrame; 

public class YouThinkThisIsAGame extends JFrame { 
private Life facebook; 

public YouThinkThisIsAGame() { 
    super("I'm Blue da ba dee da ba die"); 
    Life kyle = new Life(); 
    add(kyle); 
    //setSize(kyle.getALife()[0].length * 5, kyle.getALife().length * 5); 
    setSize(500, 500); 
    setVisible(true); 
    setMaximumSize(getSize()); 
    setMinimumSize(getSize()); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
} 

public static void main(String[] args) { 
    YouThinkThisIsAGame stuff = new YouThinkThisIsAGame(); 
    while (true) { 
     stuff.facebook.repaint(); 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
} 

И расширяющий класс JPanel здесь:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import javax.swing.JPanel; 

public class Life extends JPanel { 

private Cell[][] grid; 
Color life; 

{ 
    life = new Color(0, 175, 0); 
    initializeGrid(1300, 800, 0.025); 
} 

public void paint(Graphics G) { 
    super.paint(G); 
    Graphics2D g2d = (Graphics2D) G; 
    drawGrid(g2d); 
} 


/** Me attempting to be funny */ 
public String getLife() { 
    return null; 
} 

/** Also trying to be funny */ 
public Cell[][] getALife() { 
    return grid; 
} 


public void drawGrid(Graphics2D g) { 
    for (int i = 0; i < grid.length; i++) { 
     for (int j = 0; j < grid[i].length; j++) { 
      if (grid[i][j].isLiving) { 
       g.setColor(life); 
       //g.setColor(Color.WHITE); 
      } else { 
       g.setColor(Color.BLACK); 
      } 
      g.fillRect(i * 5, j * 5, 5, 5); 
     } 
    } 
} 

/** Allocates a new grid of cells of the requested dimensions and 
* sets each cell in the grid to a random living/dead state. 
* The desired percentage of living cells is passed as a 
* parameter. 
* 
* @double percent roughly, the percentage of cells that should 
* be initialized as alive 
*/ 
public void initializeGrid(int rows, int cols, double percent) { 
    grid = new Cell[rows][cols]; 
    for (int i = 0; i < rows; i++) { 
     for (int j = 0; j < cols; j++) { 
      grid[i][j] = new Cell(); 
      double x = Math.random(); 
      if (x > percent) { 
       grid[i][j].setLiving(false); 
      } else { 
       grid[i][j].setLiving(true); 
      } 
     } 
    } 
} 

/** Displays the contents of the grid to the standard output. 
*/ 
public void displayGrid() { 
    for (Cell[] cellRow : grid) { 
     for (Cell c : cellRow) { 
      if (c.isLiving()) System.out.print("0"); 
      else System.out.print("1"); 
     } 
     System.out.println(); 
    } 

} 

/** Updates the value of each cell in the array according to 
* the rules of life: 
* If the cell is currently living -- 
* if fewer than two neighboring cells are alive, die (loneliness) 
* if two or three neighboring cells are alive, live 
* if four or more neighboring cells are alive, die (overcrowding) 
* If the cell is currently dead -- 
* if precisely three neighboring cells are alive, become alive 
*/ 
public void updateGrid() { 
    Cell[][] gridCopy = new Cell[grid.length][grid[0].length]; 
    for (int i = 0; i < grid.length; i++) { 
     for (int j = 0; j < grid[i].length; j++) { 
      Cell c = new Cell(); 
      c.setLiving(grid[i][j].isLiving); 
      gridCopy[i][j] = c; 
     } 
    } 
    for (int i = 1; i < grid.length - 1; i++) { 
     for (int j = 1; j < grid[i].length - 1; j++) { 
      int adjacentAlive = 0; 
      if (i == 2 && (j == 4 || j == 3)) { 
       System.out.print(""); 
      } 
      if (i == 3 && j == 4) { 
       System.out.print(""); 
      } 
      if (gridCopy[i - 1][j - 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i][j - 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i + 1][j - 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i - 1][j].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i + 1][j].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i - 1][j + 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i][j + 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (gridCopy[i + 1][j + 1].isLiving) { 
       adjacentAlive++; 
      } 
      if (adjacentAlive == 3) { 
       grid[i][j].setLiving(true); 
      }else if (adjacentAlive == 2) { 

      } else { 
       grid[i][j].setLiving(false); 
      } 
     } 
    } 
    System.out.println(""); 
} 

/** Convenience method for setting the grid values. 
* 
* @param grid a two dimensional table of Cells 
*/ 
public void setGrid(Cell[][] grid) { 
    this.grid = grid; 
} 

public static void main(String[] args) { 
    Life life = new Life(); 
    life.initializeGrid(15, 40, 0.25); 
    life.displayGrid(); 
    while (true){ 
     try { 
      Thread.sleep(250); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     life.updateGrid(); 
     life.displayGrid(); 
    } 
} 

class Cell { 
    private boolean isLiving; 

    public void setLiving(boolean isLiving) { 
     this.isLiving = isLiving; 
    } 
    public boolean isLiving() { 
     return isLiving; 
    } 
} 
} 
+0

............. привет? –

ответ

2

У вас есть два основных метода, и я буду предположим, что тот, который вы запустили, находится в классе YouThinkThisIsAGame. Если это так, вы никогда не вызываете updateGrid() в объекте Life из этого основного метода (но вы делаете в основном), и поэтому сетка никогда не будет обновляться.

Предложения:

  • Создать тему в рамках основного метода,
  • Pass в Runnable, который имеет петлю while (true).
  • В этом цикле позвоните updateGrid() на визуализированный экземпляр Life
  • И вызовите repaint() на экземпляр Life.
  • Звоните start() на эту тему после создания.
  • Обратите внимание, что вам лучше рисовать внутри рамки paintComponent JPanel, а не метод рисования.
  • И назовите super.paintComponent(...) в этом переопределении.
  • Всегда предварите свой метод переопределения аннотацией @Override, чтобы убедиться, что вы фактически переопределяете метод.
  • Исправить ошибку NullPointerException, что вы сейчас расскажите нам о. Вы никогда не инициализируете или не используете поле facebook, а вместо этого используете теневую переменную kyle, объявленную внутри конструктора YouThinkThisIsAGame. Это единственный жизнеспособный экземпляр Life.
  • Так что избавитесь от переменной kyle, вместо этого инициализируйте и используйте поле facebook.
  • И избегать прямого доступа к любым полям объекта. Вместо этого используйте общедоступные методы класса, и вы должны создать метод только для этого, для вызова updateGrid() и repaint() снова на визуализированный Жизненный пример (вот почему я упомянул визуализированный выше - это ключ).

например, что-то вроде:

import javax.swing.JFrame; 

public class YouThinkThisIsAGame extends JFrame { 
    private Life life; // renamed to life 

    public YouThinkThisIsAGame() { 
     super("I'm Blue da ba dee da ba die"); 

     // no -- don't create a new Life variable! 
     // Life kyle = new Life(); 
     // add(kyle); 

     life = new Life(); // initialize and use the **field** 
     add(life); // and place it into the JFrame 

     setSize(500, 500); // better to have Life override getPreferredSize 
     setVisible(true); 
     setMaximumSize(getSize()); 
     setMinimumSize(getSize()); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    public void updateLife() { 
     life.updateGrid(); 
     life.repaint(); 
    } 

    public static void main(String[] args) { 
     final YouThinkThisIsAGame stuff = new YouThinkThisIsAGame(); 
     new Thread(() -> { 
      while (true) { 
       stuff.updateLife(); 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }).start(); 
    } 
} 
+0

Вы правы в основных методах, основной метод в жизни просто создает игру жизни, печатая 1 и 0 на консоли. Я должен был сделать это ясно в исходном сообщении (извините, я новичок в этом), но мой код бросает исключение NullPointerException, когда я вызываю метод repaint() в YouThinkThisIsAGame, я даже изменил метод Paint YouThinkThisIsAGame, чтобы просто быть супер .paint (g) и нарисуйте прямоугольник, и он по-прежнему дал мне нулевой указатель. Это исправить[email protected] –

+0

@TeymorBuckley: NPE очевиден - вы никогда не инициализируете или не используете поле 'facebook'! Вместо этого вы используете переменную shadow, 'kyle', внутри конструктора YouThinkThisIsAGame, почему? –

+0

@TeymorBuckley: см. Следующий править, чтобы ответить. –