0

我有一个程序,它只是一个绘制某些东西的窗口(没有计算,没有与用户的交互等)。这个程序的主 JPanel 有一个相当复杂的paintComponent 函数——它需要大约 5 到 10 毫秒来执行。

我设置了一个 Timer,它每 25 毫秒调用一次 TimerTask。TimerTask 只是在面板上调用 repaint() 。这样程序应该有 40 FPS。

但是面板的paintComponent 方法大约需要5 到10 毫秒才能执行。由于某种原因,Timer 等待 TimerTask 的 run() 方法完成(意味着它等待面板重新绘制)。这样它就不是每 25 毫秒重绘一次,而是 30-35 毫秒,导致不稳定和糟糕的 FPS。

显然我希望在后台执行计算 - 现在程序只是执行绘图然后空闲等待 25 毫秒,而不是执行绘图并仅等待剩余时间。

我尝试过使用 swing.Timer 而不是 util.Timer,但它不起作用(它是一样的)。

我尝试使用两个单独的计时器,一个用于在 BufferedImage 上绘制图形,另一个用于将 BufferedImage 放在 JPanel 上。这在性能方面要好一些,但会闪烁。

那么如何才能真正在后台绘制图形呢?

4

1 回答 1

0

您将要做到这一点的最佳方法已经在答案中。

在背景中绘制。

您需要将图形渲染到单独的图像上,然后在 JPanel 请求时将该图像渲染到 JPanel 上。

但是,您的解决方案的一个问题是静态睡眠。您可能想要创建一个新线程。该线程将负责渲染到图像上。然后,根据已经过去了多少时间,也可以睡到你需要的剩余时间。

private final BufferedImage render = new BufferedImage(screen_width, screen_height, BufferedImage.TYPE_RGB);

public void run(){
    final long start = System.nanoTime();
    renderGraphicsOnto(render.getGraphics());
    final renderTime = System.nanoTime() - start;
    try {
        Thread.sleep(25 - renderTime / 1000000); // convert to milliseconds
    } catch(final Exception ignored){
    }
}

这只是您可能希望如何处理的一个小示例。没有任何形式的静态睡眠由javax.swing.Timerjava.util.TimerTask不会实现这一点。

于 2013-11-05T23:45:26.257 回答