我正在编写一个简单的Java Swing应用程序,该应用程序被设计为课程的演示。该程序的目的是可视化递归方法的进度(特别是迷宫的递归解决方案)。我希望能够在递归方法执行时更新JComponent的外观,因此从Swing的角度来看,不能从Timer类中单独触发更新,我收集的是动画的常用方法。 / p>
我的第一个想法只是在我想重绘可视化时调用repaint()。但是递归方法本身是在JButton的事件处理程序中调用的,这意味着对repaint()的所有调用都会被延迟,直到事件处理程序终止 - 而我所看到的只是动画的最后一帧。我发现如果我调用update(),我可以立即进行绘图,如下所示:
getRootPane().getContentPane().update(getGraphics());
try {
Thread.sleep(25);
} catch (Exception e) {
}
除了动画闪烁之外,这几乎可以正常工作。我知道Swing是双缓冲的,但显然getGraphics给了我主动缓冲区而不是后台缓冲区。我看不到任何方法可以让我访问后台缓冲区。
所以我正在寻找一种解决方案,允许我在递归过程中重新绘制组件并给我一个无闪烁的动画。有没有办法在执行事件处理程序时激活内置双缓冲?尝试实现我自己的缓冲系统会更好吗?或者我正在尝试做什么只是不可能/可取的Swing?
(最后一点,这是我在这里发表的第一篇文章。我试过写一个好问题,但是如果我遗漏了什么请告诉我很好,下次我会尽力做得更好。谢谢!)
答案 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#。