Java getGraphics()返回null

时间:2012-08-17 17:03:56

标签: java swing

我开始学习用Java创建游戏,我正在使用的方法之一包括BufferedImage。这是我得到的错误:

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

从这段代码:

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

}

设置类:

package tm;

public class Settings {

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

}

屏幕等级:

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

}

3 个答案:

答案 0 :(得分:3)

返回null的不是getGraphics(),而是前一个函数createImage()。来自createImage()的组件文档:

  

返回屏幕外可绘制图像,可用于双倍图像   缓冲。 如果组件不是,则返回值可以为null   可显示的。如果,这将永远发生   GraphicsEnvironment.isHeadless()返回true。

在offscreenImage上调用getGraphics()时,你会得到一个NullPointerException,它是空的。

答案 1 :(得分:1)

抛出NullPointer异常的原因是你在错误的位置初始化了offScreenImage和offScr。

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

此代码应该在函数paint中。为了得到结果,Game类应该像这样定义。另外一个提示最好将变量inn settings类声明为public static final,以便可以以静态方式访问它们。如下定义,对您的Game类进行少许更改。我认为这应该对你有帮助。

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

答案 2 :(得分:0)

因为createImage仅在Component“可显示”之后才能工作,例如它附加到一个可见的JFrame,你当前的代码不会工作。

有几种方法可以解决它。

  • 将JFrame作为参数添加到ctor并在调用create component之前将Game添加到JFrame - 只要JFrame.add不调用部分初始化的Game实例覆盖的任何方法,这应该有效。

    Game(JFrame jf){
        jf.add(this);
        ...
    }
    
    JFrame mainFrame = new JFrame();
    mainFrame.setVisible(true);
    Game game = new Game(mainFrame);
    
  • 在将游戏添加到JFrame后调用另一个init方法。这很难看,因为在调用此方法之前,Game对象尚未完全初始化。

    Game game = new Game();
    JFrame mainFrame = new JFrame();
    mainFrame.add(game);
    mainFrame.setVisible(true);
    game.init();
    
  • One way找出组件可显示的时间是监听HierarchyEvent。您可以修改答案中显示的监听器来调用createImage而不是打印“显示”。 (该答案提供的课程也需要extends HierarchyListener才能工作)