繁体   English   中英

Java getGraphics()返回null

[英]Java getGraphics() returning null

我开始学习用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();
    }

}

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

返回屏幕外可绘制图像,可用于双缓冲。 如果组件不可显示,则返回值可以为null。 如果GraphicsEnvironment.isHeadless()返回true,则总会发生这种情况。

然后在offscreenImage上调用getGraphics()时得到NullPointerException,该值为null。

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

由于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); 
  • 创建一个额外的init方法,在将游戏添加到JFrame后调用。 这很难看,因为在调用此方法之前,Game对象尚未完全初始化。

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

暂无
暂无

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

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