我有一个带有自定义 paintComponent() 实现的 JPanel 子类。它正在以 50fps 的速度刷新。它的大小通常在 500x300 像素范围内。我看到一些闪烁(不是太糟糕但很明显),并且我插入了一些调试代码,表明 Swing/EDT 正在跳过(大概)冗余绘制。我猜这是因为 EDT 没有给 paintComponent() 提供足够的时间来始终完成,或者 EDT 花费了太多时间。
我的想法是我需要获取当前实现 paintComponent() 的代码(这不是很复杂但也不是完全微不足道)并重构它,以便它在自己的线程(或至少不是 EDT)上执行并绘制到图像缓冲区。然后我在我的自定义 JPanel 上实现 paintComponent 并从 ImageBuffer 绘制(渲染)到屏幕(实际上是到 Swing 组件后面的缓冲区,因为我对解决方案的研究让我了解了一些关于 Swing 被(默认情况下)双缓冲的信息,尽管我'对此并不完全清楚)。如果从 ImageBuffer 到 JPanel 的渲染确实比我构建 ImageBuffer 的实现更快,那么我将朝着正确的方向前进。
这对我来说是正确的设计方向吗?
更新
我修改了我的实现,如下面的响应中所述:
1)创建一个缓冲图像
BufferedImage myBufferedImage = new BufferedImage(mySize.width,mySize.height,BufferedImage.TYPE_INT_ARGB)
2) 创建一个专用于执行处理以确定要绘制什么的线程。
3) 将之前在paintComponent() 中的代码移动到由专用线程执行的另一个方法中。在这个方法的最后,调用 repaint();
4)创建一个新的paintComponent(),它只是调用g.drawImage(myBufferedImage,0,0,null);
5) 在我之前调用 repaint() 的地方,触发 myThread 对 myBufferedImage 执行绘图。
正如预测的那样,这是一场灾难。更糟糕的闪烁和迟缓,部分绘画等。我相信这是由于争用读/写 myBufferedImage(如下所述)。因此,我在写入时(在专用绘图线程中)创建了一个锁并锁定 myBufferedImage,并在调用 Graphics2D.drawImage() 之前等待在 paintComponent() 中获得该锁;闪烁和部分绘制消失了——但性能并不比我在paintComponent(因此在EDT)中为绘图进行所有计算时更好(甚至可能更差)。
这让我在这一点上难住了。