Java getGraphics()返回null

Java getGraphics()返回null,java,swing,Java,Swing,我开始学习用Java创建游戏,我使用的方法之一包括BuffereImage。这是我得到的错误: "Exception in thread "main" java.lang.NullPointerException at tm.Game.init(Game.java:48) at tm.Game.<init>(Game.java:54)" 设置类: package tm; public class Settings { public final int

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

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

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()
的组件文档中:

返回屏幕外可绘制的图像,该图像可用于双击 缓冲如果组件不可用,则返回值可能为空 可显示。如果 GraphicsEnvironment.ishadless()返回true


然后,在offscreenImage上调用
getGraphics()
时,会出现NullPointerException异常,该异常为null。

因为createImage仅在组件“可显示”后才能工作,例如,它连接到可见的JFrame上,所以当前代码无法工作

有几种方法可以解决这个问题

  • 在调用create组件之前,将JFrame作为参数添加到ctor中,并将游戏添加到JFrame中-只要JFrame.Add不调用部分初始化的游戏实例覆盖的任何方法,这应该可以工作

    Game(JFrame jf){
        jf.add(this);
        ...
    }
    
    JFrame mainFrame = new JFrame();
    mainFrame.setVisible(true);
    Game game = new Game(mainFrame);
    
  • 创建一个附加的init方法,在将游戏添加到JFrame后调用该方法。这很难看,因为在调用此方法之前,游戏对象并没有真正完全初始化

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


引发NullPointer异常的原因是您在错误的位置初始化了offScreenImage和offScr

offscreenImage = (BufferedImage) createImage(Settings.GAME`WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();
此代码应位于函数绘制中。为了得到结果,游戏类应该这样定义。另一个技巧是最好将设置类中的变量声明为publicstaticfinal,这样就可以以静态方式访问它们。对游戏类进行如下定义的小改动。我想这应该对你有帮助

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
在哪里定义?@DanW
Image java.awt.Component.createImage(int-width,int-height)
您是否尝试过用
super()
调用JPanel中的构造函数?为什么您不只是序列化类,而是抑制有关序列化的警告?@DanW您能解释一下如何快速完成吗?我对Java不是很有经验。Kierrow,我真的不知道,我在创建和设置类时很匆忙,我通常会序列化它。
GraphicsEnvironment.ishadless()
返回
false
,那么解决这个问题的好方法是什么呢?@ThomasMosey您的JPanel没有注册JFrame,创建JFrame,使其可见并将面板添加到其中。+1 josefx
GraphicsEnvironment.isHeadless()
应返回false,但请确保
isDisplayable()
也返回true。@josefx编辑过的OP,对不起,忘了在我用于JFrame中添加类。您必须从
init()
中删除
createImage()
,或调用
init()
仅当JPanel添加到JFrame而不是其构造函数中时。
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();
    }
}