3

I'm starting to learn to create Games in Java, and one of the methods I'm using includes BufferedImage. This is the error I get:

"Exception in thread "main" java.lang.NullPointerException
     at tm.Game.init(Game.java:48)
     at tm.Game.<init>(Game.java:54)"

From this code:

package tm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Game extends JPanel implements Runnable {
    private Settings Settings;

    private Thread t;
    private BufferedImage offscreenImage;
    private Graphics offscr;

    public void run() {
        while(true) {
            repaint();

            try {
                Thread.sleep(1000/30);
            } catch (InterruptedException e) { }
        }
    }

    public void paint(Graphics g) {
        offscr.setColor(Color.blue);
        offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);

        offscr.setColor(Color.white);
        offscr.drawString("Lolz", 10, 10);

        g.drawImage(offscreenImage, 0, 0, this);
    }

    public void update(Graphics g) {
        paint(g);
    }

    public void init() {
        t = new Thread(this);
        t.start();

        offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
        offscr = offscreenImage.getGraphics();
    }

    public Game() {
        Settings = new Settings();

        init();
    }

}

Settings Class:

package tm;

public class Settings {

    public final int GAME_WIDTH = 500;
    public final int GAME_HEIGHT = 500;

}

Screen Class:

package tm;

import javax.swing.JFrame;

public class Screen extends JFrame {
    private static final long serialVersionUID = 1L;
    private JFrame mainScreen;
    private Game mainGame;
    private Settings Settings;

    public Screen() {
        mainGame = new Game();
        Settings = new Settings();

        mainScreen = new JFrame();
        mainScreen.add(mainGame);
        mainScreen.setSize(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
        mainScreen.setTitle("Lolz");
        mainScreen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainScreen.setResizable(false);
        mainScreen.setVisible(true);
    }

    public static void main(String[] args) {
        new Screen();
    }

}
6
  • Where is the method createImage defined? Commented Aug 17, 2012 at 17:09
  • @DanW Image java.awt.Component.createImage(int width, int height) Commented Aug 17, 2012 at 17:12
  • Have you tried calling the constructor in JPanel with super()? Commented Aug 17, 2012 at 17:13
  • Why do you suppress warnings about serialization instead of just serializing the class? Commented Aug 17, 2012 at 17:14
  • @DanW Could you explain how to do that quickly please? I'm not that experienced in Java. Kierrow, I really don't know, I was rushing whilst creating and setting up the Class, I usually to serialize it. Commented Aug 17, 2012 at 17:18

3 Answers 3

3

It is not getGraphics() that returns null but rather the previous function createImage(). From the Component documentation for createImage():

returns an off-screen drawable image, which can be used for double buffering. The return value may be null if the component is not displayable. This will always happen if GraphicsEnvironment.isHeadless() returns true.

You then get a NullPointerException when calling getGraphics() on offscreenImage which is null.

Sign up to request clarification or add additional context in comments.

9 Comments

GraphicsEnvironment.isHeadless() returns false, so what would be a good way of working around this?
@ThomasMosey your JPanel is not registered with a JFrame, create a JFrame, make it visible and add the panel to it.
+1 josefx. GraphicsEnvironment.isHeadless() should return false but make sure isDisplayable() also returns true.
@josefx Edited OP, sorry, forgot to add the class in I use for JFrame.
You'll have to remove the createImage() from init() or call init() only once the JPanel is added to the JFrame and not in his constructor.
|
1

The reason that throw NullPointer exception is that you initialized the offScreenImage and offScr in wrong place.

offscreenImage = (BufferedImage) createImage(Settings.GAME`WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();

This code should be in the function paint. To get the results the Game class should be defined like this. And another tip it is better to declare variables inn Settings class to public static final so that they can be accessed in static way. Make little change to your Game class as defined below. I think this should help you.

package tm;

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import tm.Screen.Settings;

public class Game extends JPanel implements Runnable {
    // private Setting Settings;

    private Thread t;
    private BufferedImage offscreenImage;
    private Graphics offscr;

    public void run() {
        while (true) {
            repaint();

            try {
                Thread.sleep(1000 / 30);
            } catch (InterruptedException e) {
            }
        }
    }

    public void paint(Graphics g) {

        if (offscreenImage == null) {

            offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH,
                    Settings.GAME_HEIGHT);
        }
        offscr = offscreenImage.getGraphics();
        offscr.setColor(Color.black);
        offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
        offscr.setColor(Color.white);
        offscr.drawString("Lolz", 10, 10);

        g.drawImage(offscreenImage, 0, 0, this);
    }

    public void update(Graphics g) {
        paint(g);
    }


    public void init() {
        t = new Thread(this);
        t.start();
    }

    public Game() {
        init();
    }
}

Comments

0

Since createImage only works after the Component is "displayable" e.g. it is attached to a visible JFrame your current code wont work.

There are several ways you can deal with it.

  • Add JFrame as a parameter to the ctor and add the Game to the JFrame before calling create component - this should work as long as JFrame.add does not call any methods overridden by the partially initialized Game instance.

    Game(JFrame jf){
        jf.add(this);
        ...
    }
    
    JFrame mainFrame = new JFrame();
    mainFrame.setVisible(true);
    Game game = new Game(mainFrame);
    
  • Make an additional init method which is called after adding Game to the JFrame. This is ugly since the Game object is not really fully initialized until this method is called.

    Game game = new Game();
    JFrame mainFrame = new JFrame();
    mainFrame.add(game);
    mainFrame.setVisible(true);
    game.init();
    
  • One way to find out when the component is displayable is to listen for a HierarchyEvent. You could modify the Listener shown in the answer to call createImage instead of printing "showing". (The class provided by that answer also needs a extends HierarchyListener to work)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.