简体   繁体   English

组件/ JPanel repaint()方法问题

[英]Component/JPanel repaint() method issues

I am trying to make Conway's game of life but I am having issues using the repaint() method. 我正在尝试制作Conway的生活游戏,但是在使用repaint()方法时遇到了问题。 I have created a class that extends JPanel and I am calling super.paint(g) when I override paint, plus I am not overriding the repaint() method, yet I have had no luck. 我创建了一个扩展JPanel的类,当我覆盖paint时我正在调用super.paint(g) ,而且我没有覆盖repaint()方法,但是我没有运气。 The main method I test this in is the here (please excuse my terrible identifiers): 我在其中测试的主要方法是这里(请原谅我糟糕的标识符):

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();
        }
    }
}
}

And the JPanel extending class is here: 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;
    }
}
}

You have two main methods, and I'll assume that the one that you run is the one within the YouThinkThisIsAGame class. 您有两种主要方法,我假设您运行的方法是YouThinkThisIsAGame类中的一种。 If so, you never call updateGrid() on the Life object from this main method (but you do in the other main method), and so the grid never will update. 如果是这样,则永远不会从此main方法调用Life对象上的updateGrid() (但在另一个 main方法中调用),因此网格将永远不会更新。

Suggestions: 意见建议:

  • Create a Thread within the main method, 在main方法中创建一个线程,
  • Pass in a Runnable that has the while (true) loop. 传递具有while (true)循环的Runnable。
  • Within that loop, call updateGrid() on the visualized Life instance 在该循环中,在可视化的Life实例上调用updateGrid()
  • And call repaint() on the Life instance. 并在Life实例上调用repaint()
  • Call start() on that Thread after creation. 创建后在该线程上调用start()
  • Note that you're better off drawing within the JPanel's paintComponent override, not the paint method. 请注意,最好在JPanel的paintComponent覆盖范围内绘制,而不要在paint方法内绘制。
  • And call the super.paintComponent(...) within that override. 并在该覆盖范围内调用super.paintComponent(...)
  • Always precede your override method with an @Override annotation to have the compiler check that you are in fact overriding the method. 始终在覆盖方法之前添加@Override批注,以使编译器检查您实际上是否覆盖了该方法。
  • Fix the NullPointerException that you now tell us about. 修复您现在告诉我们的NullPointerException。 You never initializing or using the facebook field but instead are using a shadow variable, kyle, declared inside of the YouThinkThisIsAGame constructor. 您从不初始化或使用facebook字段,而是使用在YouThinkThisIsAGame构造函数内部声明的阴影变量kyle。 This is the only viable Life instance going. 这是唯一可行的Life实例。
  • So get rid of the kyle variable, instead initialize and use the facebook field. 因此,摆脱kyle变量,而是初始化并使用facebook字段。
  • And avoid directly accessing any fields of an object. 并避免直接访问对象的任何字段。 Instead go through public methods of the class, and you should create a method just for this, for calling updateGrid() and repaint() again on the visualized Life instance (that's why I mentioned visualized above -- it's key). 而是通过类的公共方法,您应该为此创建一个方法,以便在可视化的 Life实例上再次调用updateGrid()repaint() (这就是我在上面提到的可视化的原因-这是关键)。

eg, something like: 例如,类似:

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM