将BufferedImage绘制到JFrame会导致NullPointerException即使初始化图像和图形

时间:2017-02-26 00:57:11

标签: java game-engine

所以我正在编写一个2D游戏引擎,而现在,我正在尝试使用简单的Chunk进行渲染,但是当我这样做时,我会得到一个空白窗口,并且会出现以下内容:我的控制台:

javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(Unknown Source)
at sfortress.graphics.image.TileIcon.<init>(TileIcon.java:31)
at sfortress.game.tile.Tiles.init(Tiles.java:15)
at sfortress.SFortress.init(SFortress.java:28)
at sfortress.SFortress.main(SFortress.java:31)
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(Unknown Source)
at sfortress.graphics.image.TileIcon.<init>(TileIcon.java:31)
at sfortress.game.tile.Tiles.init(Tiles.java:21)
at sfortress.SFortress.init(SFortress.java:28)
at sfortress.SFortress.main(SFortress.java:31)
TILES: 2
Initializing 16x16 Chunk...     [ DONE ]
Generating Chunk...      [ OKAY ]
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(Unknown Source)
at sfortress.graphics.image.TileIcon.<init>(TileIcon.java:31)
at sfortress.SFortress.run0(SFortress.java:39)
at sfortress.game.tile.Tiles.init(Tiles.java:28)
at sfortress.SFortress.init(SFortress.java:28)
at sfortress.SFortress.main(SFortress.java:31)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at japi.window.panel.ImagePanel.paintComponent(ImagePanel.java:55)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at japi.window.panel.ImagePanel.paintComponent(ImagePanel.java:55)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at japi.window.panel.ImagePanel.paintComponent(ImagePanel.java:55)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

我在过去的一周半里重写了我的代码8或9(我丢失了数次),但我只能通过直接在draw方法中调用ImageIO.read(File file)来渲染任何内容(一旦我真正让引擎工作,这将是非常低效的)如果有人知道如何解决这个问题,我真的很感激。所有涉及的代码如下:

SFortress.java

package sfortress;

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.File;

import util.OS;

import japi.window.panel.ImagePanel;

import sfortress.*;
import sfortress.game.*;
import sfortress.game.character.*;
import sfortress.game.data.positioning.*;
import sfortress.game.tile.*;
import sfortress.graphics.image.TileIcon;
import sfortress.world.chunk.*;

public class SFortress {
  public static String sPath;

  public static void init() {
    sPath = System.getProperty("user.dir");
    OS.init();
    Game.init();
    Tiles.init();
  }
  public static void main(String[] args) {
    init();
  }
  public static void run0() {
    JFrame frame = new JFrame();
    ImagePanel panel = new ImagePanel();
    Chunk chunk = new Chunk(16,new Position("chunk",0,0,0)).generate();
    BufferedImage image = null;
    image = chunk.draw();
    panel.setImage(image);

    frame.add(panel);
    frame.setSize(512,512);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setTitle("Chunk Rendering Test v5");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }

  public static String path(String input) {
    return ("." + sPath + "." + input).replace("..",".").replace('.',OS.dirChar);
  }
}

Chunk.java

package sfortress.world.chunk;

import java.awt.*;
import java.awt.image.BufferedImage;

import sfortress.game.Game;
import sfortress.game.data.positioning.*;
import sfortress.world.chunk.TileSlot;

import static sfortress.game.Game.world;

public class Chunk {
  public TileSlot[][][] slots;
  public int scale;
  public Position loc;

  public Chunk(int scale,Position loc) {
    System.out.print("Initializing " + scale + 'x' + scale + " Chunk...");
    this.scale = scale;
    this.loc = loc;
    this.slots = new TileSlot[scale][scale][scale];
    for (int x = 0; x < scale; x++) {
      for (int y = 0; y < scale; y++) {
        for (int z = 0; z < scale; z++) {
          slots[x][y][z] = new TileSlot();
        }
      }
    }
    System.out.println("     [ DONE ]");
  }

  /*public void load() {
    new ChunkFile(Game.world.getPath(".chunks.c-x"+loc.x+"_y"+loc.y+"_z"+loc.z+".chunk"),this).load();
  }
  public void unLoad() {
    new ChunkFile(Game.world.getPath(".chunks.c-x"+loc.x+"_y"+loc.y+"_z"+loc.z+".chunk"),this).save();
  }*/

  private Position pgd(int x, int y, int z, Side side) {
    Position pk = null;
    if (side == Side.TOP) {
      pk = new Position("tile",y,x,z);
    } else if (side == Side.BOTTOM) {
      pk = new Position("tile",-y,x,z);
    } else if (side == Side.LEFT) {
      pk = new Position("tile",z,-y,-x);
    } else if (side == Side.RIGHT) {
      pk = new Position("tile",z,y,x);
    } else if (side == Side.FRONT) {
      pk = new Position("tile",z,x,-y);
    } else if (side == Side.BACK) {
      pk = new Position("tile",z,-x,y);
    }
    return pk;
  }
  public BufferedImage draw() {
    Side side = Game.viewerSide;
    Position pos = Game.viewerPosition;
    Position kloc = loc.convert("pixel");
    int px = Game.spriteScale * scale;
    BufferedImage image = new BufferedImage(px,px,BufferedImage.TYPE_INT_ARGB);
    Graphics g = image.createGraphics();
    for (int x = 0; x < scale; x++) {
      for (int y = 0; y < scale; y++) {
        for (int z = 0; z < scale; z++) {
          Position p = pgd(x,y,z,side);
          g.drawImage(slots[p.x][p.y][p.z].getTile().draw(side)[0],0,0,null);
        }
      }
    }
    g.dispose();
    return image;
  }

  public Chunk generate() {
    System.out.print("Generating Chunk...");
    for (int x = 0; x < scale; x++) {
      for (int y = 0; y < scale; y++) {
        for (int z = 0; z < scale; z++) {
          slots[x][y][z].setTile(sfortress.game.tile.Tiles.rand());
        }
      }
    }
    System.out.println("      [ OKAY ]");
    return this;
  }
}

Game.java

package sfortress.game;

import sfortress.game.data.positioning.*;
import sfortress.world.World;

public final class Game {
  public static World world;
  public static int spriteScale;
  public static Position viewerPosition;
  public static Side viewerSide;

  public static void init() {
    spriteScale = 16;
    viewerPosition = new Position("pixel",127,127,255);
    viewerSide = Side.TOP;
    world = new World("Unnamed",12,16);
  }
}

TileIcon.java

package sfortress.graphics.image;

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

import sfortress.SFortress;
import sfortress.game.data.positioning.*;
import sfortress.graphics.image.GImage;

public class TileIcon extends GImage {
  private BufferedImage top;
  private BufferedImage bottom;
  private BufferedImage right;
  private BufferedImage left;
  private BufferedImage front;
  private BufferedImage back;

  public float glow;

  public TileIcon() {}
  public TileIcon(String name) {
    String p = SFortress.path(".data.sprites.name.");
    File fTop = new File(p + "top.png");
    File fBot = new File(p + "bottom.png");
    File fRig = new File(p + "right.png");
    File fLef = new File(p + "left.png");
    File fFro = new File(p + "front.png");
    File fBac = new File(p + "back.png");
    try {
      front = ImageIO.read(fFro);
      back = ImageIO.read(fBac);
      left = ImageIO.read(fLef);
      right = ImageIO.read(fRig);
      top = ImageIO.read(fTop);
      bottom = ImageIO.read(fBot);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void tick() {}
  public BufferedImage[] draw(Side side) {
    BufferedImage image = null;
    switch (side.toString().toLowerCase()) {
      case "bottom":
        image = bottom;
        break;
      case "right":
        image = right;
        break;
      case "left":
        image = left;
        break;
      case "front":
        image = front;
        break;
      case "back":
        image = back;
        break;
      default:
        image = top;
        break;
    }
    return new BufferedImage[] {image,sfortress.graphics.Renderer.makeGlowLayer(image)};
  }
}

Tiles.java

package sfortress.game.tile;

import java.util.*;

import sfortress.game.tile.*;
import sfortress.graphics.image.TileIcon;

public class Tiles {
  public static ArrayList<Tile> tiles = new ArrayList<Tile>();

  public static void init() {
    SolidTile stone = new SolidTile();
    stone.name = "Stone";
    stone.id = "tiles.stone";
    stone.icon = new TileIcon("tiles.stone");
    stone.meltingPoint = 3000f;
    stone.fluidForm = null;
    SolidTile sandstone = new SolidTile();
    sandstone.name = "Sandstone";
    sandstone.id = "tiles.sandstone";
    sandstone.icon = new TileIcon("tiles.sandstone");
    sandstone.meltingPoint = 3000f;
    sandstone.fluidForm = null;
    tiles.add(stone);
    tiles.add(sandstone);
    System.out.println("TILES: " + tiles.size());

    sfortress.SFortress.run0();
  }

  public static Tile rand() {
    Random random = new Random();
    int index = random.nextInt(tiles.size()-1);
    return tiles.get(index);
  }
}

VoidIcon.java

package sfortress.graphics.image;

import java.awt.image.BufferedImage;

import sfortress.game.Game;

public class VoidIcon extends TileIcon {
  public void tick() {
    return;
  }
  public BufferedImage[] draw() {
    return new BufferedImage[] {new BufferedImage(Game.spriteScale,Game.spriteScale,BufferedImage.TYPE_INT_ARGB),null};
  }
}

GImage.java

package sfortress.graphics.image;

import java.awt.image.BufferedImage;
import sfortress.game.data.positioning.*;

public abstract class GImage {
  public float glow;

  public abstract void tick();
  public abstract BufferedImage[] draw(Side side);
}

Tile.java

package sfortress.game.tile;

import java.awt.image.BufferedImage;

import sfortress.game.data.positioning.*;
import sfortress.graphics.image.TileIcon;
import sfortress.world.chunk.TileSlot;

public abstract class Tile {
  public String name;
  public String id;
  public TileIcon icon;
  public float density;

  protected TileSlot slot;

  public abstract Tile fabricate();

  public void tick() {
    icon.tick();
  }
  public void destroy() {
    return;
  }
  public BufferedImage[] draw(Side side) {
    return icon.draw(side);
  }
  public void set(TileSlot slot) {
    this.slot = slot;
  }
}

ImagePanel.java

package japi.window.panel;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.*;

import java.io.File;
import java.io.IOException;

import javax.swing.*;
import javax.imageio.ImageIO;

public class ImagePanel extends JPanel {
  private BufferedImage image;

  public ImagePanel() {
  }
  public ImagePanel(String path) {
    try {
      setImage(ImageIO.read(new File(path)));
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }
  public ImagePanel(BufferedImage image) {
    setImage(image);
  }

  public void setImage(String image) {
    try {
      this.image = ImageIO.read(new File(image));
    } catch (Exception e) {
      e.printStackTrace();
    }
    repaint();
  }
  public void setImage(BufferedImage image) {
    this.image = image;
    repaint();
  }

  @Override
  public int getWidth() {
    return 512;
  }

  @Override
  public int getHeight() {
    return 512;
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(image.getScaledInstance(this.getWidth(),this.getHeight(),Image.SCALE_SMOOTH), 0, 0, null);
  }
}

另外,请告诉我如果我错过了您认为可能有助于解决此问题的文件(我总共有36个文件)。

1 个答案:

答案 0 :(得分:1)

你的问题是由这样的事情引起的:

try {
  image = chunk.draw();
} catch (Exception e) {
  e.printStackTrace();
}

你正在捕捉异常然后......基本上......忽略它们。它被称为异常压缩,这是一个坏主意。

在这种特殊情况下,当异常被压扁时,您不会为image分配任何内容。如果image开始null,它将保持null。如果您的代码尝试使用它(不检查null)那么NPE是最有可能的结果。

  

如果有人知道如何解决这个问题,我真的很感激。

解决方案:

  1. 摆脱代码中所有异常压缩的情况。如果您无法处理已检查的异常,请让它们传播......并使应用程序崩溃。

  2. 一旦您的应用程序因意外异常而崩溃,请找出导致它们的原因并解决问题。

  3. 在这种情况下,看起来你的图像加载有问题。评论表明,您可能正在使用Java无法理解的图像格式。

    您评论道:

      

    好吧,考虑到Windows Photo Viewer中加载的所有图像,我说它们没有损坏

    除此之外。建议是图像格式错误,而不是它们已损坏。

    经过一番挖掘后,这里是库代码,它会抛出该消息的初始异常:

    public static BufferedImage  read(File input) throws IOException {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }
        if (!input.canRead()) {
            throw new IIOException("Can't read input file!");
        }
        ....
    }
    

    这意味着问题是您的应用程序用于映像文件的路径名是错误的(即无法解析),或者存在文件或目录权限问题。请注意,此时图像阅读器尚未尝试读取文件。它只是在尝试打开它之前应用了一些测试。

    (根据您的最终评论,这 问题。)