java createImage(int width, int height) 的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1541845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:01:05  来源:igfitidea点击:

Problems with createImage(int width, int height)

javaimagenullpointerexceptionimage.createimage

提问by Jonathan

I have the following code, which is run every 10ms as part of a game:

我有以下代码,它作为游戏的一部分每 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);
    }
}

The problem is that it enters the if statement which checks for the Image being null, even after I attempt to define the image. I looked around, and it seems that createImage() will return null if GraphicsEnvironment.isHeadless() returns true.

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

I don't understand exactly what the isHeadless() method's purpose is, but I thought it might have something to do with the compiler or IDE, so I tried on two, both of which get the same error (Eclipse, and BlueJ). Anyone have any idea what the source of the error is, and how I might fix it?

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

Thanks in advance

提前致谢

Jonathan

乔纳森

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

………………………………………………………………………………………………………………………………………………………… ………………

EDIT: I am using java.awt.Component.createImage(int width, int height). The purpose of this method is to ensure the creation of, and edit an Image that will contain the view of the player of the game, that will later be drawn to the screen by means of a JPanel. Here is some more code if this helps at all:

编辑:我正在使用 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

Hope this helps clear things up a bit, Jonathan

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

回答by camickr

Instead of createImage(...), I usually use a BufferedImage.

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

回答by 3.14

I had exactly the same problem after I tried to implement Doublebuffering for a fractal generator. My solution: I took the example from a book but changed it (without knowing the consequences) in the way that I ran createImage INSIDE the constructor. This produced the nullpointer. Then i put this

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

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

inside the update-method and it worked !! Because update is called AFTER the object has been constructed.

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

回答by BoldJet

Try overriding the addNotify() method in the JPanel you are extending. This is a good place to 'launch' your animation from, rather that the constructor for example. Make sure to include the line super.addNotify();

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

public void addNotify() { super.addNotify(); startGame(); }

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

Best of luck

祝你好运

回答by William Rose

According to the docs for java.awt.Component, createImage can also return null if the component is not displayable, which is most likely what's happening.

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

For what you are trying to do you should look at the BufferedImage class, as this isn't tied to the component.

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

回答by Suresh Kumar

Looks like the thread is starting up earlier than the component is actually displayed on screen. To make sure this doesn't happen, you can override the paint(Graphics g) method of JPanel and put the code in the thread's run() method inside of the paint method. In your thread's run() methods, just call repaint().

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

e.g:

例如:

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

and in your run() method:

并在您的 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();
    }
}

回答by jsight

isHeadless will only return true if you are running in a non-GUI environment (eg, within a server or servlet container).

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

I believe that your problem is within your createImage method itself. Can you give us more context? Which createImage method is being called and what is its implementation?

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

回答by stuart brand

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);
    }

}