【问题标题】:Problems with createImage(int width, int height)createImage 的问题(int width, int height)
【发布时间】:2009-10-09 04:45:24
【问题描述】:

我有以下代码,它作为游戏的一部分每 10 毫秒运行一次:

private void gameRender()
{
    if(dbImage == null)
    {
        //createImage() returns null if GraphicsEnvironment.isHeadless()
        //returns true. (java.awt.GraphicsEnvironment)
        dbImage = createImage(PWIDTH, PHEIGHT);
        if(dbImage == null)
        {
            System.out.println("dbImage is null"); //Error recieved
            return;
        }
        else
        dbg = dbImage.getGraphics();
    }

    //clear the background
    dbg.setColor(Color.white);
    dbg.fillRect(0, 0, PWIDTH, PHEIGHT);

    //draw game elements...

    if(gameOver)
    {
        gameOverMessage(dbg);
    }
}

问题在于,即使在我尝试定义图像之后,它也会进入检查图像是否为空的 if 语句。我环顾四周,似乎如果 GraphicsEnvironment.isHeadless() 返回 true,createImage() 将返回 null。

我不完全理解 isHeadless() 方法的目的是什么,但我认为它可能与编译器或 IDE 有关,所以我尝试了两个,两者都得到相同的错误(Eclipse 和蓝J)。任何人都知道错误的来源是什么,我该如何解决?

提前致谢

乔纳森

.................................................. .....................

编辑: 我正在使用 java.awt.Component.createImage(int width, int height)。此方法的目的是确保创建和编辑包含游戏玩家视图的图像,稍后将通过 JPanel 将其绘制到屏幕上。 如果这有帮助,这里还有一些代码:

public class Sim2D extends JPanel implements Runnable
{

private static final int PWIDTH = 500;
private static final int PHEIGHT = 400;
private volatile boolean running = true;
private volatile boolean gameOver = false;

private Thread animator;

//gameRender()
private Graphics dbg;
private Image dbImage = null;


public Sim2D()
{   
    setBackground(Color.white);
    setPreferredSize(new Dimension(PWIDTH, PHEIGHT));

    setFocusable(true);
    requestFocus(); //Sim2D now recieves key events
    readyForTermination();

    addMouseListener( new MouseAdapter() {
        public void mousePressed(MouseEvent e)
        { testPress(e.getX(), e.getY()); }
    });
} //end of constructor

private void testPress(int x, int y)
{
    if(!gameOver)
    {
        gameOver = true; //end game at mousepress
    }
} //end of testPress()


private void readyForTermination()
{
    addKeyListener( new KeyAdapter() {
        public void keyPressed(KeyEvent e)
        { int keyCode = e.getKeyCode();
            if((keyCode == KeyEvent.VK_ESCAPE) ||
               (keyCode == KeyEvent.VK_Q) ||
               (keyCode == KeyEvent.VK_END) ||
               ((keyCode == KeyEvent.VK_C) && e.isControlDown()) )
            {
                running = false; //end process on above list of keypresses
            }
        }
    });
} //end of readyForTermination()

public void addNotify()
{
    super.addNotify(); //creates the peer
    startGame();       //start the thread
} //end of addNotify()

public void startGame()
{
    if(animator == null || !running)
    {
        animator = new Thread(this);
        animator.start();
    }
} //end of startGame()


//run method for world
public void run()
{
    while(running)
    {
        long beforeTime, timeDiff, sleepTime;

        beforeTime = System.nanoTime();

        gameUpdate(); //updates objects in game (step event in game)
        gameRender(); //renders image
        paintScreen(); //paints rendered image to screen

        timeDiff = (System.nanoTime() - beforeTime) / 1000000;
        sleepTime = 10 - timeDiff;

        if(sleepTime <= 0) //if took longer than 10ms
        {
            sleepTime = 5; //sleep a bit anyways
        }

        try{
            Thread.sleep(sleepTime); //sleep by allotted time (attempts to keep this loop to about 10ms)
        }
        catch(InterruptedException ex){}

        beforeTime = System.nanoTime();
    }

    System.exit(0);
} //end of run()

private void gameRender()
{
    if(dbImage == null)
    {
        dbImage = createImage(PWIDTH, PHEIGHT);
        if(dbImage == null)
        {
            System.out.println("dbImage is null");
            return;
        }
        else
        dbg = dbImage.getGraphics();
    }

    //clear the background
    dbg.setColor(Color.white);
    dbg.fillRect(0, 0, PWIDTH, PHEIGHT);

    //draw game elements...

    if(gameOver)
    {
        gameOverMessage(dbg);
    }
} //end of gameRender()

} //end of class Sim2D

希望这有助于澄清一些事情, 乔纳森

【问题讨论】:

    标签: java image nullpointerexception image.createimage


    【解决方案1】:

    我通常使用 BufferedImage 来代替 createImage(...)。

    【讨论】:

    • 我出于教育目的关注文本,如果可能的话,我更愿意继续使用图像,这样我就可以尽可能接近代码示例等。是否有另一种解决方法?使用 BufferedImage 还有其他好处和/或理由吗?
    • camickr 提出了一个很好的观点。此外,Image 是一个抽象类。每当您使用图像时,您实际上是在处理 Image 的几种可能实现中的一种。 BufferedImage 就是其中之一,它是一个有意义的使用。
    • 好的,我会尝试使用 BufferedImage。谢谢。
    【解决方案2】:

    在尝试为分形生成器实现双缓冲后,我遇到了完全相同的问题。我的解决方案: 我从一本书中拿了这个例子,但改变了它(不知道后果),我在构造函数中运行 createImage 的方式。这产生了空指针。然后我把这个

    if (_dbImage == null) {
    _dbImage = createImage(getSize().width, getSize().height);
    _dbGraphics = (Graphics2D)_dbImage.getGraphics();
    }
    

    在更新方法中,它起作用了!!因为更新是在对象被构造之后调用的。

    【讨论】:

      【解决方案3】:

      根据 java.awt.Component 的文档,如果组件不可显示,createImage 也可以返回 null,这很可能是正在发生的事情。

      对于您要执行的操作,您应该查看 BufferedImage 类,因为它与组件无关。

      【讨论】:

        【解决方案4】:

        尝试覆盖您正在扩展的 JPanel 中的 addNotify() 方法。这是一个“启动”动画的好地方,而不是例如构造函数。确保包含行 super.addNotify();

        public void addNotify() { super.addNotify(); 开始游戏(); }

        祝你好运

        【讨论】:

          【解决方案5】:

          看起来线程在组件实际显示在屏幕上之前启动。为确保不会发生这种情况,您可以覆盖 JPanel 的 paint(Graphics g) 方法,并将代码放在该线程的 run() 方法中的 paint 方法内。在线程的 run() 方法中,只需调用 repaint()。

          例如:

          public void paint(Graphics g){
                  **gameUpdate(); //updates objects in game (step event in game)
                  gameRender(); //renders image
                  paintScreen(); //paints rendered image to screen**
          }
          

          在你的 run() 方法中:

          public void run(){
           while(running)
              {
                  long beforeTime, timeDiff, sleepTime;
          
                  beforeTime = System.nanoTime();
          
                  **repaint();**
          
                  timeDiff = (System.nanoTime() - beforeTime) / 1000000;
                  sleepTime = 10 - timeDiff;
          
                  if(sleepTime <= 0) //if took longer than 10ms
                  {
                      sleepTime = 5; //sleep a bit anyways
                  }
          
                  try{
                      Thread.sleep(sleepTime); //sleep by allotted time (attempts to keep this loop to about 10ms)
                  }
                  catch(InterruptedException ex){}
          
                  beforeTime = System.nanoTime();
              }
          }
          

          【讨论】:

            【解决方案6】:

            只有在非 GUI 环境(例如,在服务器或 servlet 容器中)运行时,isHeadless 才会返回 true。

            我相信您的问题出在您的 createImage 方法本身。你能给我们更多的背景吗?调用了哪个 createImage 方法,它的实现是什么?

            【讨论】:

              【解决方案7】:
              package javagame;
              
              import java.awt.BorderLayout;
              import javax.swing.JFrame;
              
              /**
               *
               * @author stuart
               */
              public class Main {
              
                  /**
                   * @param args the command line arguments
                   */
                  public static void main(String[] args) {
                      // TODO code application logic here
                      JFrame frame= new JFrame();
                      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                      frame.setBounds(100, 100, 500, 400);
              
                      frame.add(new GamePanel(), BorderLayout.CENTER);
                      frame.setVisible(true);
                  }
              
              }
              

              【讨论】:

                猜你喜欢
                • 2014-07-05
                • 2013-11-20
                • 1970-01-01
                • 2012-12-14
                • 1970-01-01
                • 2018-01-13
                • 2012-10-28
                • 2012-11-25
                • 2020-04-11
                相关资源
                最近更新 更多