Java:Swing的安全动画

我正在创建一个使用JFrame,JPanel,JLabel和所有其他类型的swing组件的程序。

我想要做的是在专用于此动画的单独JPanel上创建2D动画。 所以我将覆盖paintComponent(Graphics g)方法。

我有使用for循环+线程制作动画的经验,但是我听说线程在摆动时并不安全。

因此,使用Runnable接口制作动画是否安全? 如果不是我应该使用什么(例如计时器),请举例说明如何最好地使用它(或链接到网页)。

编辑:

感谢Jeff,我将使用Timer来创建动画。 对于这个问题的未来观众,这是一个我在大约5分钟内编写的快速程序,原谅脏代码。

我还添加了一些快速评论。

import java.awt.*; import java.awt.event.*; import javax.swing.*; class JFrameAnimation extends JFrame implements ActionListener { JPanel panel; Timer timer; int x, y; public JFrameAnimation () { super (); setDefaultCloseOperation (EXIT_ON_CLOSE); timer = new Timer (15, this); //@ First param is the delay (in milliseconds) therefore this animation is updated every 15 ms. The shorter the delay, the faster the animation. //This class iplements ActionListener, and that is where the animation variables are updated. Timer passes an ActionEvent after each 15 ms. } public void run () { panel = new JPanel () { public void paintComponent (Graphics g) //The JPanel paint method we are overriding. { g.setColor (Color.white); g.fillRect (0, 0, 500, 500); //Setting panel background (white in this case); //g.fillRect (-1 + x, -1 + y, 50, 50); //This is to erase the black remains of the animation. (not used because the background is always redrawn. g.setColor (Color.black); g.fillRect (0 + x, 0 + y, 50, 50); //This is the animation. } } ; panel.setPreferredSize (new Dimension (500, 500)); //Setting the panel size getContentPane ().add (panel); //Adding panel to frame. pack (); setVisible (true); timer.start (); //This starts the animation. } public void actionPerformed (ActionEvent e) { x++; y++; if (x == 250) timer.stop (); //This stops the animation once it reaches a certain distance. panel.repaint (); //This is what paints the animation again (IMPORTANT: won't work without this). panel.revalidate (); //This isn't necessary, I like having it just in case. } public static void main (String[] args) { new JFrameAnimation ().run (); //Start our new application. } } 

吉米,我认为你误解了线程如何在Swing中运行。 您必须使用一个名为Event Dispatch Thread的特定线程来对swing组件进行任何更新(有一些特殊的例外,我不会在这里讨论)。 您可以使用swing计时器设置在事件派发线程上运行的定期任务。 请参阅此示例,了解如何使用Swing计时器。 http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html

您还应该阅读Event Dispatch Thread,以便了解它在Swing中的位置http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

Java还提供了各种在SwingUtilities类中使用Swing的方法,特别是invokeLaterinvokeAndWait ,它们将在事件派发线程上运行代码。

虽然很好理解EDT和SwingUtilities(每个人都在做Swing应该这样做)如果你要做很多动画我会建议使用TimingFramework 。 这样您就可以将更多精力集中在设计上,并且可以更好地控制“速率”。 本质上,时序框架使用Swing计时器,因此回调在EDT上。 作为Filthy-rich客户集合的一部分,作者提供了该章节 。

玩的开心!