createImage(int width, int height) 的问题
我有以下代码,作为游戏的一部分每 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 和 BlueJ)。任何人都知道错误的根源是什么,以及我如何解决它?
预先感谢
乔纳森
................................................. .....................
编辑: 我正在使用 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
希望这有助于澄清一些事情, 乔纳森
I have the following code, which is run every 10ms as part of a game:
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.
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?
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:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我通常使用 BufferedImage,而不是 createImage(...)。
Instead of createImage(...), I usually use a BufferedImage.
根据 java.awt.Component 的文档,如果组件不可显示,createImage 也可以返回 null,这很可能是发生的情况。
对于您想要执行的操作,您应该查看 BufferedImage 类,因为它与组件无关。
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.
For what you are trying to do you should look at the BufferedImage class, as this isn't tied to the component.
在尝试为分形生成器实现双缓冲后,我遇到了完全相同的问题。我的解决方案:
我从书中获取了示例,但以在构造函数内运行 createImage 的方式对其进行了更改(不知道后果)。这产生了空指针。然后我将其放入
更新方法中并且它起作用了!因为 update 是在对象构造完成之后调用的。
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
inside the update-method and it worked !! Because update is called AFTER the object has been constructed.
尝试重写您正在扩展的 JPanel 中的 addNotify() 方法。这是“启动”动画的好地方,而不是构造函数。确保包含 super.addNotify(); 行
公共无效addNotify()
{
super.addNotify();
开始游戏();
祝你
好运
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();
public void addNotify()
{
super.addNotify();
startGame();
}
Best of luck
看起来线程的启动时间早于组件实际显示在屏幕上的时间。为了确保这种情况不会发生,您可以重写 JPanel 的 Paint(Graphics g) 方法,并将代码放在 Paint 方法内部线程的 run() 方法中。在线程的 run() 方法中,只需调用 repaint() 即可。
例如:
在你的 run() 方法中:
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().
e.g:
and in your run() method:
仅当您在非 GUI 环境(例如,在服务器或 servlet 容器内)中运行时,isHeadless 才会返回 true。
我相信您的问题出在您的 createImage 方法本身内。您能给我们提供更多背景信息吗?正在调用哪个 createImage 方法以及它的实现是什么?
isHeadless will only return true if you are running in a non-GUI environment (eg, within a server or servlet container).
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?