Java:在网格上填充矩形

5

首先声明这是一个任务。我不希望答案被直接给出,但是我想知道是什么导致了我的问题。

我正在实现康威生命游戏。点击单元格应该改变颜色,表示该单元格已切换到存活状态。如果再次点击,则应返回默认颜色。

当我在窗口的任何位置点击时,程序会在第56行抛出空指针异常。我已经困在这里一天左右了,所以任何帮助都将不胜感激。谢谢!

以下是代码:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class VisibleGrid extends JPanel implements MouseListener, KeyListener{ 

  CellGrid cellGrid;
  Graphics rect;

  public VisibleGrid(){
    addMouseListener(this);
    cellGrid = new CellGrid();
  }

  //Draw the grid of cells, 7px wide, 75 times to create 75x75 grid
  public void paint(Graphics g){
    for(int i=0; i<525;i=i+7){
      for(int j = 0; j<525; j=j+7){
        g.drawRect(i ,j,7,7);       
      }
    }   
  }

  //auxillary method called to fill in rectangles
  public void paint(Graphics g, int x, int y){
    g.fillRect(x, y, 7, 7);
    repaint();

  }

  //main method, adds this JPanel to a JFrame and sets up the GUI  
  public static void main(String[] args){
    JFrame j = new JFrame("Conway's Game of Life");
    j.setLayout(new BorderLayout());
    j.add(new VisibleGrid(), BorderLayout.CENTER);
    JTextArea info = new JTextArea("Press S to Start, E to End");
    info.setEditable(false);
    j.add(info, BorderLayout.SOUTH);
    j.setSize(530,565);
    j.setVisible(true);
  }

  //these methods are to satisfy the compiler/interface
  //Begin Mouse Events
  public void mouseExited(MouseEvent e){}
  public void mouseEntered(MouseEvent e){}
  public void mouseReleased(MouseEvent e){}
  public void mousePressed(MouseEvent e){}
  public void mouseClicked(MouseEvent e){
    //fill the selected rectangle
    rect.fillRect(e.getX(), e.getY(), 7,7); 
    repaint();

    //set the corresponding cell in the grid to alive
    int row = e.getY() /7;
    int column = e.getX() /7;
     cellGrid.getCell(row, column).setAlive(true);
  } 
  //End Mouse Events

//These methods are to satisfy the compiler/interface
//Begin KeyEvents
  public void keyReleased(KeyEvent e){}
  public void keyPressed(KeyEvent e){}
  public void keyTyped(KeyEvent e){}



}

1
第56行是哪一行?当我复制/粘贴代码时,它是int column = e.getX() /7; 这看起来不对。 - Chetter Hummin
我敢打赌第56行是 _rect.fillRect(e.getX(), e.getY(), 7,7);_。 - guido
正如@guido所说,确保在访问rect之前初始化或拥有有效的引用。 - Rupak
2个回答

3
问题在于您的rect字段从未被设置任何内容,因此它保持为null。调用rect.drawRect将导致您看到的NullPointerException。
如果我没记错的话,Swing Graphics对象并不喜欢你在它们没有期望你进行任何绘画时绘制它们。因此,我建议不要将在调用paint()时获取的Graphics对象存储在rect之类的字段中。如果您想重新绘制窗口的一部分,最好告诉Swing需要重新绘制窗口的哪个部分,然后让它调用您的paint()方法。
在您的mouseClicked()方法中,我删除了对rect.fillRect()的调用,并将对repaint()的调用移到了该方法的末尾。我还修改了paint()方法,以便在单元格存活时绘制填充矩形,在单元格未存活时绘制未填充矩形。这样做后,您的代码似乎可以正常工作,我可以单击某些单元格并将它们变成黑色。
我有一些关于您的代码改进的建议。我会把最后两个留给您作为练习:
  • 我建议在main()中添加代码行j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);。这将使应用程序在关闭窗口时正常退出。
  • 目前,每当单个单元格发生变化时,您的代码都会重新绘制整个75×75网格。可以更改代码,使其仅重绘更改的单元格。您可以向repaint()方法传递一个Rectangle, 这告诉Swing“只需要重绘此组件的一部分”。在paint方法中,可以使用Graphics类的getClipBounds()方法获取此矩形,并使用它来确定要重新绘制哪个单元格或多个单元格。
  • drawRect只绘制矩形的轮廓。如果一个细胞死亡,您的paint方法将无法清除网格中现有的黑色矩形。您可以通过绘制填充白色矩形并在其上绘制黑色轮廓矩形来修复此问题。

非常感谢您提供如此有帮助的答案!我现在已经几乎完成了游戏的实现,只需要完成实际游戏算法部分,但GUI部分已经完成。再次感谢您,伙计。 - NickD720

0
你确定CellGrid对象已经填充了细胞吗?我不是Java专家,但是在你的代码中我没有看到这个初始化...

是的,CellGrid对象在其构造函数中填充了Cell对象。我刚刚解决了程序的GUI部分。谢谢! - NickD720

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接