【问题标题】:Flicker-free JComponent rendering within a Swing event handlerSwing 事件处理程序中的无闪烁 JComponent 呈现
【发布时间】:2013-03-24 09:50:32
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 我认为您已经包含了所有内容 :) 尽管查看递归以尝试查明可能会挤入 repaint() 的位置可能会有所帮助。您最终可能会遇到一些条件递归和/或重绘,以便仅在适当时调用它。
  • 为什么不维护对前一个缓冲区的引用并用它进行更新?

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


【解决方案1】:

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

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

要渲染动画,您可以在递归方法中调用myComponent.repaint(),或者启动一个摇摆计时器(感谢@mKorbel 指出),它基本上如下所示:

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

我推荐后一种方法,因为您的递归方法可能对 Swing 组件一无所知(除非您通过“ProgressListener”或其他方式将其解耦)。

看来你不仅仅是初学者,我只是给出了一些关于如何做的提示。如果您需要更多意见,请随时提出。

【讨论】:

  • 谢谢;这给了我足够的继续。关键见解是在另一个线程上运行递归将允许 repaint() 正常使用。我也喜欢你的其他建议,尽管我试图让其余代码保持简单,以便递归仍然是重点。
  • 不是,永远不会(当然可以),而是在今天的 Java6/7 中使用 Swing Timer
  • @mKorbel 过去几年没怎么玩 Swing,谢谢你指点我javax.swing.Timer
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2019-04-03
    • 2020-06-28
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多