我有一个问题。最近,我正在研究使用Java实现硬件渲染的方法。我的目标不是使用OpenGL等外部库。我在网站上发现了一篇详细说明如何操作的帖子。
这就是代码(我重命名了一些项目):
@Override
public void paint(Graphics g) {
createVolatileImage();
do {
GraphicsConfiguration gc = getGraphicsConfiguration();
Graphics offscreenGraphics = volatileImage.getGraphics();
int validationCode = volatileImage.validate(gc);
if (validationCode == VolatileImage.IMAGE_INCOMPATIBLE) {
createVolatileImage();
}
offscreenGraphics.setColor(getBackground());
offscreenGraphics.fillRect(0, 0, getSize().width, getSize().height);
offscreenGraphics.setColor(getForeground());
paint(offscreenGraphics);
g.drawImage(volatileImage, 0, 0, this);
} while (volatileImage.contentsLost());
}
private void createVolatileImage() {
GraphicsConfiguration gc = getGraphicsConfiguration();
volatileImage = gc.createCompatibleVolatileImage(getWidth(), getHeight());
}
不幸的是,如果我调整窗口大小 - paint(Graphics)方法(在Canvas类中)会在一秒内被调用1000次,从而导致OutOfMemoryException。
之前有没有遇到过这个? 非常感谢提前!
答案 0 :(得分:0)
您获得OutOfMemoryException的原因是因为您从未清理过VolatileImage
。我看到它的方式是,每次调用VolatileImage
时都会分配一个新的paint()
,这可能会发生数百次(或者在你的情况下超过一千次)每秒。除非您释放VolatileImage
使用的内存或修复内容,以便分配一次而不是每帧一次,否则应用程序的内存空间将会膨胀,直到您崩溃JVM为止。尝试在渲染循环结束时添加对offscreengraphics.dispose()
的调用。另请阅读Javadoc。
编辑:
另一个有用的reference。
答案 1 :(得分:0)
我真的不认为你的paint方法应该有一个循环。它应该为每个需要绘制的动作绘制一次,然后返回。当您拖动屏幕时,OS / env将负责将重绘消息一遍又一遍地发送到您的应用程序。如果可能的话你应该重新绘制然后返回。没有循环检查内容是否丢失,操作系统会告诉你何时进行绘画。
答案 2 :(得分:0)
如Painting in AWT and Swing中所述,这是在AWT中绘画时的预期行为。特别是,在调整组件大小时会发生系统触发的绘制操作。正如@rjacks所说,您需要dispose()
paint()
中创建的所有资源。