【问题标题】:Java Swing - loading graphics in the backgroundJava Swing - 在后台加载图形
【发布时间】:2013-11-05 21:19:22
【问题描述】:

我有一个程序,它只是一个绘制某些东西的窗口(没有计算,没有与用户的交互等)。这个程序的主 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 上。这在性能方面要好一些,但会闪烁。

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

【问题讨论】:

  • javaxswing.Timer 是正确的选择,对于example;请编辑您的问题以包含一个 sscce 来展示您所描述的问题。
  • “但闪烁” 听起来你是直接在顶层容器上绘画。

标签: java swing graphics timer


【解决方案1】:

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

在背景中绘制。

您需要将图形渲染到单独的图像上,然后在 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 提供的任何形式的静态睡眠都无法实现此目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 2012-02-05
    相关资源
    最近更新 更多