3

私はJavaでゲームを作成する方法を学び始めており、使用しているメソッドの1つに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();
    }

}
4

3 に答える 3

3

nullを返すのではgetGraphics()なく、前の関数を返しますcreateImage()。のコンポーネントドキュメントからcreateImage()

は、画面外の描画可能な画像を返します。これは、ダブルバッファリングに使用できます。コンポーネントが表示できない場合、戻り値はnullになる可能性があります。GraphicsEnvironment.isHeadless()がtrueを返す場合、これは常に発生します。

getGraphics()次に、 nullであるoffscreenImageを呼び出すと、NullPointerExceptionが発生します。

于 2012-08-17T17:19:12.497 に答える
1

NullPointer例外をスローする理由は、offScreenImageとoffScrを間違った場所で初期化したためです。

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

このコードは関数ペイントに含まれている必要があります。結果を得るには、Gameクラスを次のように定義する必要があります。また、静的な方法でアクセスできるように、変数innSettingsクラスを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();
    }
}
于 2012-08-18T05:14:01.133 に答える
0

createImageは、コンポーネントが「表示可能」になった後でのみ機能するため、たとえば、表示されているJFrameにアタッチされている場合、現在のコードは機能しません。

あなたがそれに対処することができるいくつかの方法があります。

  • JFrameをctorのパラメーターとして追加し、createコンポーネントを呼び出す前にGameをJFrameに追加します。これは、JFrame.addが、部分的に初期化されたGameインスタンスによってオーバーライドされたメソッドを呼び出さない限り機能します。

    Game(JFrame jf){
        jf.add(this);
        ...
    }
    
    JFrame mainFrame = new JFrame();
    mainFrame.setVisible(true);
    Game game = new Game(mainFrame);
    
  • GameをJFrameに追加した後に呼び出される追加のinitメソッドを作成します。このメソッドが呼び出されるまでGameオブジェクトは実際には完全に初期化されないため、これは醜いです。

    Game game = new Game();
    JFrame mainFrame = new JFrame();
    mainFrame.add(game);
    mainFrame.setVisible(true);
    game.init();
    
  • コンポーネントがいつ表示可能かを確認する1つの方法は、HierarchyEventをリッスンすることです。「showing」を出力する代わりに、回答に示されているリスナーを変更してcreateImageを呼び出すことができます。(その回答によって提供されるクラスも機能する必要がありますextends HierarchyListener

于 2012-08-17T21:27:52.597 に答える