【问题标题】:java efficient repainting on moving objectsjava对移动物体进行高效重绘
【发布时间】:2015-12-31 03:39:02
【问题描述】:

我想知道在我的情况下最有效的重绘方法是什么,以及如何去做。

我有一个JFrame,其中包含一个JPanel。这个JPanel 包含一些 AWT 图形。其中一些图形是固定的,它们不会移动。此面板中的其他一些图形(在固定图形之上)确实会移动。布局每 3 秒更新一次。固定的图形需要相当多的数学才能绘制,所以我可能不想重新绘制所有图形,而只想重新绘制移动的图形。

这是我想出的可能性:

  1. 将固定图形和移动图形放在两个单独的面板中,并且只重绘一个面板,它们相互重叠。
  2. 将两个不同的Graphics 对象添加到面板(一个用于固定图形,一个用于移动),并且只重绘一个图形对象。 (这甚至可能吗?)
  3. 也许我不知道其他方式?

【问题讨论】:

  • “固定的图形需要一些安静的数学来绘制..” 将它们绘制到BufferedImage 并首先绘制图像。
  • @AndrewThompson 那我还是每次都要重绘 BufferedImage 吧?

标签: java swing graphics awt repaint


【解决方案1】:

如果背景在窗口的生命周期内从未改变,那么您可以在构建时执行所有复杂的计算并为其创建一个BufferedImage 对象。

然后在您的重绘中,使用

将图像绘制到图形对象上
graphics.drawImage( bufferedImage, ... )

这应该比每次重绘都重新计算背景要快得多,因为您一遍又一遍地重复使用相同的BufferedImage

编辑 如果调整了窗口大小,您可以使用

boolean Graphics.drawImage(Image img,
   int dstx1, int dsty1, int dstx2, int dsty2,
   int srcx1, int srcy1, int srcx2, int srcy2,
   ImageObserver observer);

坐标为当前窗口大小的方法。

如果您需要在调整大小的窗口上重新计算背景图像,您可以添加一个侦听器来侦听调整大小事件。

this.addComponentListener(new ComponentAdapter() 
{  
    public void componentResized(ComponentEvent evt) {           
        //...
    }
});

【讨论】:

  • 如何确保在调整窗口大小时重新计算 BufferedImage?
  • "..在调整窗口大小时重新计算?" 是否需要重新计算,或者只是拉伸以填充新大小? “那我还是每次都要重新绘制 BufferedImage 对吧?” 当然可以,但是绘制图像非常快。
  • @Xander 更新答案以解决您的调整大小问题
  • 我实现了这个解决方案,但是当我将图形绘制到 BufferedImage 然后到面板时,与直接在面板上绘制相比,我损失了很多质量。为什么是这样?您对如何解决这个问题有什么建议吗?
  • 听起来您的缓冲图像与您的面板相比不是一个合适的尺寸?也许缩放使图像过于块状?如果是这样,可以尝试我在调整组件大小时重新创建 bufferedImage 的第二种解决方案
【解决方案2】:

就像其他人说的那样,使用BufferedImage 作为固定对象。对于移动的对象,您应该计算需要重绘的区域的边界(即所有移动对象的旧边界框联合/新边界框)。首先将该区域的固定图形部分向下沿 Blit,然后对移动的对象进行 Blit。

如果您还没有,您还应该查看double buffering。绘制到屏幕外缓冲区然后在准备好后翻转到屏幕上通常是一种更好的体验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多