我正在编写一个简单的Java Swing应用程序,该应用程序被设计为类(class)的演示。该程序的目的是可视化递归方法(特别是迷宫的递归解决方案)的进度。我希望能够在执行递归方法时更新JComponent的外观,因此从Swing的角度来看,无法从Timer类中单独触发更新,我收集的Timer类是动画的常用方法。
我的第一个想法就是只要我想重绘可视化效果就调用repaint()。但是递归方法本身在JButton的事件处理程序中被调用,这意味着所有对repaint()的调用都被延迟,直到事件处理程序终止为止,而我所看到的只是动画的最后一帧。我发现,如果我改为调用update(),则可以立即进行绘制,如下所示:
getRootPane().getContentPane().update(getGraphics());
try {
Thread.sleep(25);
} catch (Exception e) {
}
除了动画闪烁外,这几乎可以工作。我知道Swing是双缓冲的,但是显然getGraphics为我提供了 Activity 缓冲区,而不是后缓冲区。我看不到任何可以让我访问后台缓冲区的方法。
因此,我正在寻找一种解决方案,该解决方案允许我在递归的中间重新绘制该组件并提供无闪烁的动画。有没有一种方法可以在执行事件处理程序时激活内置的双缓冲?尝试实现自己的缓冲系统会更好吗?还是我正在尝试做的事情在Swing中是不可能/不建议的?
(最后一点,这是我在这里的第一篇文章。我试图写一个好的问题,但是如果我错过了任何事情,请告诉我,我会在下一次做得更好。谢谢!)
最佳答案
首先,您应该not be executing long-running actions in the Event Dispatch Thread,我认为这是动画闪烁的原因之一。
因此,我建议您在按下按钮时启动一个执行您的递归方法的线程(并可能在 Activity 完成之前将其禁用)。
要渲染动画,您可以从递归方法中调用myComponent.repaint()
,或者启动一个Swing计时器(感谢@mKorbel对此进行修饰),其基本上如下所示:
ActionListener repaintTrigger = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
myComponent.repaint();
}
};
new Timer(25, repaintTrigger).start();
我建议使用后一种方法,因为您的递归方法可能应该对Swing组件一无所知(除非您通过“ProgressListener”将其解耦)。
看来您不光是个初学者,我只是给了一些建议。如果您需要更多意见,请随时提出。