Okay, my question isn't exactly about how to use Swing or AWT, but this IS a GUI app. Somehow, one of my member variables becomes null when it should actual refer to an object. So...here are some details. I have a plethora of classes in this program:
LifeFrame - extends JFrame and initializes the GUI
LifePanel - extends JPanel and contains all other graphic objects
WorldPanel - I do my custom drawing here. This is where the member reference lives that mysteriously becomes null.
World - Parent class for my Game of Life simulation. This has two subclasses: one for text-only and another for use in a GUI app
GraphicWorld - extends World; Most importantly, this has a paint() and other methods for graphical manipulation
OptionsDialog - so far this dialog allows the user to set the width and height of the "world" grid. I might add other customization features in the future.
When I run the program, the grid paints fine. I can click on it to create "life" and click on the various buttons to run the simulation. This means that the reference to a GraphicWorld in the WorldPanel class actually has an object (i.e. isn't null). When I open the OptionsDialog to change the size of the world, I get a NullPointerException, though.
The biggest mystery is that it used to work perfectly. I'm not sure what I changed recently to cause this problem.
I guess I should also post some of my code so you can get a better idea how I have this put together. I'll try to just post the relevant parts. If anyone wants to see other sections, pleast let me know.
<pre>
// LifeFrame.java
public class LifeFrame
extends CloseableFrame
{
static public void main(
String[] args)
{
new LifeFrame().show();
}
public LifeFrame()
{
setTitle("The Game of Life");
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(d.width / 4, d.height / 4, d.width / 2, d.height / 2);
p = new LifePanel();
getContentPane().add(new LifePanel());
createMenu();
}
private void createMenu()
{
// snip...
a = new AbstractAction[1];
a[0] = new AbstractAction("Options...")
{
public void actionPerformed(ActionEvent e)
{
options.show();
if(options.getResult() == OptionsDialog.OK)
{
System.out.println("Setting size");
p.setWorldSize(options.getWorldSize());
}
}
};
mb.addMenu("Edit", a);
}
LifePanel p;
OptionsDialog options;
JFileChooser fileDialog;
}
// LifePanel.java
public class LifePanel
extends JPanel
{
// snip several methods
public void setWorldSize(Dimension d)
{
w.setWorldSize(d);
}
private WorldPanel w;
}
// WorldPanel.java
public class WorldPanel
extends JPanel
{
// some methods are omitted
public WorldPanel()
{
genCount = 0;
genLabel = new JLabel("Generation " + genCount);
add(genLabel);
addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
try
{
world.setCell(e.getX(), e.getY());
repaint();
}
catch(IndexOutOfBoundsException ex)
{
}
}
});
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(world == null) newWorld();
world.paint(g, getWidth(), getHeight());
}
public void newWorld(File file)
{
System.out.println("WorldPanel.newWorld()");
world = new GraphicWorld(file);
genCount = 0;
updateLabel();
repaint();
}
public void setWorldSize(Dimension d)
{
System.out.println("Making a new world");
if(world == null) System.out.println("World is null");
world.setSize(d);
System.out.println("world:" + world);
}
private void newWorld()
{
newWorld(10, 10);
}
private void newWorld(int w, int h)
{
world = new GraphicWorld(w, h);
genCount = 0;
updateLabel();
repaint();
}
private void updateLabel()
{
genLabel.setText("Generation " + genCount);
genLabel.repaint();
}
private GraphicWorld world;
}
// GraphicWorld.java
public class GraphicWorld
extends World
{
public void paint(Graphics g, int w, int h)
{
x = (w - width * CELL_SIZE) / 2;
y = (h - height * CELL_SIZE) / 2;
paint(g);
}
public void paint(Graphics g)
{
System.out.println("in paint:" + this);
for(int i = 0; i < width + 1; ++i)
{
int xPos = x + i * CELL_SIZE;
g.drawLine(xPos, y, xPos, y + height * CELL_SIZE);
}
for(int i = 0; i < height + 1; ++i)
{
int yPos = y + i * CELL_SIZE;
g.drawLine(x, yPos, x + width * CELL_SIZE, yPos);
}
for(int i = 0; i < width; ++i)
for(int j = 0; j < height; ++j)
if(board[i][j])
{
int left = x + i * CELL_SIZE;
int top = y + j * CELL_SIZE;
g.fillRect(left, top, CELL_SIZE, CELL_SIZE);
}
}
public void setCell(int x, int y)
throws IndexOutOfBoundsException
{
Point p = new Point(x, y);
Rectangle r = new Rectangle(this.x, this.y,
width * CELL_SIZE,
height * CELL_SIZE);
if(!r.contains(p))
throw new IndexOutOfBoundsException("Coordinates are out of bounds");
int newX = (x - this.x) / CELL_SIZE;
int newY = (y - this.y) / CELL_SIZE;
board[newX][newY] = !board[newX][newY];
}
final private int CELL_SIZE = 10;
private int x, y;
}
</pre>
I apologize for posting so much code. I tried to eliminate any that isn't important to my question. Note that any apparent compiler errors in the code above are a result of editing. My program DOES compile.
I will really appreciate any input about fixing my problem.
Thank you,
Layne
[This message has been edited by Layne Lund (edited December 07, 2001).]