在java中使用super.paintComponent(g)或getGraphics()

时间:2014-05-15 12:32:53

标签: java graphics 2d

我'对于一些事情有点困惑:

示例代码,显示我的问题,这是不可编译的

// 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()或没有任何差异。

我的程序运行得很好,但我有这个配音。

2 个答案:

答案 0 :(得分:3)

  

这是一个很好的做法

不,这实际上是非常可怕且容易出错。这假设这是Component#getGraphics方法。问题是Swing使用被动渲染算法,也就是说,Swing决定何时以及应该重新绘制什么,并且出于优化原因这样做。

这意味着更新不是常规的,这在制作动画时非常有用,并且可以在任何时候出于任何原因而发生,其中许多原因是您根本无法控制而无法控制。

由于这些原因,绘画应该在其中一种绘画方法中完成,最好是基于paintComponent类的JComponent。这样,当Swing决定进行重新绘制时,你知道它并且可以相应地更新输出,其中两个,它不会使用getGraphics清除你之前绘制的内容,这可能会导致闪烁...

你也遇到了潜在的线程问题,因为你的线程试图绘制到Graphics上下文,所以事件调度线程可能不会结束......所有绘画应该在EDT的背景下完成(基于组件的绘画)

您可以尝试使用BufferedStrategy,这可以让您直接控制绘画过程,但这限制了您对AWT库的限制。在你的情况下,不知道这是好还是坏。

  

另外一件事,graphic.dispose()如何正常工作?因为   试图删除这行代码,没有任何反应。

dispose基本上会释放Graphics上下文可能持有的所有本机资源。一般的经验法则,如果你没有创造,你就不会处置它。

因此,如果您使用Graphics#createBufferedImage#createGraphics获取Graphics上下文,则应在完成后调用dispose

在用于执行组件绘制的dispose上下文中调用Grpahics的某些系统(例如传递给paintComponent或从getGraphcis获取的内容)可以阻止进一步的内容从被绘制。

同样地,不处理你创建的Graphics个上下文会导致内存泄漏,因为他们不会收集垃圾......

答案 1 :(得分:1)

关于Swing中的“好”或“正确”绘画有很多问题,所以这个问题可以被认为是重复的,我不会在这里重复一下应该在上下文中阅读的内容,例如, Lesson about Performing Custom Painting

但是,要简明扼要地总结最重要的信息:

  • 您应该永远getGraphics上致电Component。它可能会以任何其他方式“无效”返回nullGraphics个对象。它迟早会以一种形式或另一种形式失败
  • 你应该使用你在那里收到的paintComponent对象作为参数,在paintComponent方法(或从Graphics调用的方法)中进行所有绘制操作
  • 您是否调用Graphics#dispose方法可能无法立即显示“立即”。你应该paintComponent收到的那个上调用它。您应该Graphics对象上调用它,该对象是您从BufferedImage获得的,或者是您通过调用Graphics#create()创建的对象。当您不调用它时,此可能会导致内存泄漏,只有在应用程序运行一段时间后才会发现。