Swing事件处理程序中无闪烁的JComponent渲染

时间:2013-04-02 22:09:38

标签: java swing animation concurrency event-dispatch-thread

我正在编写一个简单的Java Swing应用程序,该应用程序被设计为课程的演示。该程序的目的是可视化递归方法的进度(特别是迷宫的递归解决方案)。我希望能够在递归方法执行时更新JComponent的外观,因此从Swing的角度来看,不能从Timer类中单独触发更新,我收集的是动画的常用方法。 / p>

我的第一个想法只是在我想重绘可视化时调用repaint()。但是递归方法本身是在JButton的事件处理程序中调用的,这意味着对repaint()的所有调用都会被延迟,直到事件处理程序终止 - 而我所看到的只是动画的最后一帧。我发现如果我调用update(),我可以立即进行绘图,如下所示:

getRootPane().getContentPane().update(getGraphics());
try {
    Thread.sleep(25);
} catch (Exception e) {
}

除了动画闪烁之外,这几乎可以正常工作。我知道Swing是双缓冲的,但显然getGraphics给了我主动缓冲区而不是后台缓冲区。我看不到任何方法可以让我访问后台缓冲区。

所以我正在寻找一种解决方案,允许我在递归过程中重新绘制组件并给我一个无闪烁的动画。有没有办法在执行事件处理程序时激活内置双缓冲?尝试实现我自己的缓冲系统会更好吗?或者我正在尝试做什么只是不可能/可取的Swing?

(最后一点,这是我在这里发表的第一篇文章。我试过写一个好问题,但是如果我遗漏了什么请告诉我很好,下次我会尽力做得更好。谢谢!)

2 个答案:

答案 0 :(得分:2)

首先,您应该not be executing long-running actions in the Event Dispatch Thread,我认为这是动画闪烁的一个原因。

所以我建议在按下按钮时启动一个执行递归方法的线程(也可以在工作完成之前将其停用)。

要渲染动画,您可以在递归方法中调用myComponent.repaint(),也可以启动Swing Timer(感谢@mKorbel将其解析出来),这基本上是这样的:

ActionListener repaintTrigger = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
          myComponent.repaint();
      }
};
new Timer(25, repaintTrigger).start();

我推荐使用后一种方法,因为你的递归方法可能不应该知道关于Swing组件的任何信息(除非你通过“ProgressListener”或其他东西将它解耦)。

因为看起来你不仅仅是初学者,我只是给了一些关于该怎么做的提示。如果您需要更多输入,请随时询问。

答案 1 :(得分:0)

我实际上并不知道这是否有效但是。 我会尝试使它多线程并将递归与图形分开。我不知道这是否适用于java,但它确实适用于C#。