我'对于一些事情有点困惑:
示例代码,显示我的问题,这是不可编译的
// image
private BufferedImage image;
private Graphics2D graphic;
private changeImage;
. . .
//thread loop
while (running) {
. . .
render();
Graphics showGraphic = getGraphics();
showGraphic.drawImage(image, 0, 0, null);
showGraphic.dispose();
}
public void render(){
if(changeImage == 1)
graphic.drawImage(ImageLoader.TREE, 0, 0, null);
else if(changeImage == 2){
graphic.drawImage(ImageLoader.HOUSE, 0, 0, null);
. . .
graphic.fillRect(50,60,30,40);
}
}
我创建了一个全局对象Graphic2D
,我在render()
中绘制内容,我没有在游戏循环中调用repaint()
,这样做是不错的做法?< / strong>
我应该在循环中使用repaint()
和paintComponent()
函数吗?
另一件事,graphic.dispose()
如何正常工作? ,因为试图删除这行代码,没有任何反应。
我理解如何根据java docs , 工作dispose(),但我没有注意到dispose()或没有任何差异。
我的程序运行得很好,但我有这个配音。
答案 0 :(得分:3)
这是一个很好的做法
不,这实际上是非常可怕且容易出错。这假设这是Component#getGraphics
方法。问题是Swing使用被动渲染算法,也就是说,Swing决定何时以及应该重新绘制什么,并且出于优化原因这样做。
这意味着更新不是常规的,这在制作动画时非常有用,并且可以在任何时候出于任何原因而发生,其中许多原因是您根本无法控制而无法控制。
由于这些原因,绘画应该在其中一种绘画方法中完成,最好是基于paintComponent
类的JComponent
。这样,当Swing决定进行重新绘制时,你知道它并且可以相应地更新输出,其中两个,它不会使用getGraphics
清除你之前绘制的内容,这可能会导致闪烁...
你也遇到了潜在的线程问题,因为你的线程试图绘制到Graphics
上下文,所以事件调度线程可能不会结束......所有绘画应该在EDT的背景下完成(基于组件的绘画)
您可以尝试使用BufferedStrategy
,这可以让您直接控制绘画过程,但这限制了您对AWT库的限制。在你的情况下,不知道这是好还是坏。
另外一件事,graphic.dispose()如何正常工作?因为 试图删除这行代码,没有任何反应。
dispose
基本上会释放Graphics
上下文可能持有的所有本机资源。一般的经验法则,如果你没有创造,你就不会处置它。
因此,如果您使用Graphics#create
或BufferedImage#createGraphics
获取Graphics
上下文,则应在完成后调用dispose
。
在用于执行组件绘制的dispose
上下文中调用Grpahics
的某些系统(例如传递给paintComponent
或从getGraphcis
获取的内容)可以阻止进一步的内容从被绘制。
同样地,不处理你创建的Graphics
个上下文会导致内存泄漏,因为他们不会收集垃圾......
答案 1 :(得分:1)
关于Swing中的“好”或“正确”绘画有很多问题,所以这个问题可以被认为是重复的,我不会在这里重复一下应该在上下文中阅读的内容,例如, Lesson about Performing Custom Painting。
但是,要简明扼要地总结最重要的信息:
getGraphics
上致电Component
。它可能会以任何其他方式“无效”返回null
或Graphics
个对象。它迟早会以一种形式或另一种形式失败paintComponent
对象作为参数,在paintComponent
方法(或从Graphics
调用的方法)中进行所有绘制操作Graphics#dispose
方法可能无法立即显示“立即”。你应该不在paintComponent
收到的那个上调用它。您应该仅在Graphics
对象上调用它,该对象是您从BufferedImage
获得的,或者是您通过调用Graphics#create()
创建的对象。当您不调用它时,此可能会导致内存泄漏,只有在应用程序运行一段时间后才会发现。