爪哇;调整窗口大小后,油漆(图形)调用过多!
我有一个问题。最近我正在研究使用 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());
}
不幸的是,如果我调整窗口大小 - 绘制( Graphics )方法(在 Canvas 类中)在一秒钟内被调用大约 1,000 次,导致 OutOfMemoryException 。
以前有人遇到过这种情况吗? 预先非常感谢!
I have a question. Recently I was looking into ways to implement hardware rendering using Java. My goal was not to use an external library such as OpenGL. I found a post on a website that detailed how to do so.
This is what the code was (I renamed some items):
@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());
}
Unfortunately, if I resize the window - the paint ( Graphics ) method (in the class Canvas) gets called like 1,000 times within a second, causing an OutOfMemoryException.
Has anyone encountered this before?
Thanks a lot in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您收到 OutOfMemoryException 的原因是因为您从未清理过
VolatileImage
。在我看来,每次调用paint()
时,您都会分配一个新的VolatileImage
,这可能会发生数百次(或者在您的情况下超过一千次)第二。除非您释放VolatileImage
使用的内存或进行修复以便分配一次而不是每帧分配一次,否则应用程序的内存空间将会膨胀,直到 JVM 崩溃。尝试在渲染循环末尾添加对offscreengraphics.dispose()
的调用。另请阅读 Javadoc。编辑:
另一个有用的参考。
The reason you are getting an OutOfMemoryException is because you never clean up your
VolatileImage
. The way I see it, you are allocating a newVolatileImage
every timepaint()
is called, which can happen many hundreds (or in your case over a thousand) times per second. Unless you free the memory used by theVolatileImage
or fix things so that you make the allocation once instead of once per frame, your application's memory space will balloon until you crash the JVM. Try adding a call tooffscreengraphics.dispose()
at the end of your rendering loop. Also read the Javadoc.EDIT:
Another useful reference.
我真的不认为你的绘画方法中应该有一个循环。它应该为每个需要绘制的操作绘制一次,然后返回。当您拖动屏幕时,操作系统/环境将负责一遍又一遍地向您的应用程序发送重绘消息。如果可能的话,您应该重新粉刷,然后返回。没有循环检查内容是否丢失,操作系统会告诉您何时进行绘画。
I really don't think you should have a loop in your paint method. It should paint a single time for each action that needs a paint, then return.When you drag the screen, the OS/env will take care of dispatching repaint messages over and over to your app. You should repaint if possible then just return. No loops checking if content is lost, the OS will tell you when to do your painting.
正如在 AWT 和 Swing 中绘制中所讨论的,这是在 AWT 中绘画时的预期行为。特别是,当调整组件大小时,会发生系统触发的绘制操作。正如 @rjacks 所指出的,您需要
dispose()
在paint()
中创建的任何资源。As discussed in Painting in AWT and Swing, this is the expected behavior when painting in AWT. In particular, a system-triggered painting operation occurs when a component is resized. As @rjacks notes, you need to
dispose()
any resources created inpaint()
.