【问题标题】:Java: Safe Animations with SwingJava:使用 Swing 的安全动画
【发布时间】:2011-06-08 02:27:44
【问题描述】:

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

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

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

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

编辑:

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

我还添加了一些快速 cmets。

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.
    }
}

【问题讨论】:

  • 没有必要给你一个例子,因为在这个网站和其他网站上可以找到很多东西,如果你花点力气做一些搜索的话。祝你好运!
  • 例如,在这个链接中查看我的代码:java-label-settext-and-setbounds-clashing

标签: java swing animation jframe


【解决方案1】:

Jimmy,我认为您误解了 Swing 中线程的工作方式。您必须使用称为 Event Dispatch Thread 的特定线程来对 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 的方法,特别是 invokeLater 和 invokeAndWait,它们将在事件调度线程上运行代码。

【讨论】:

  • 好吧,我对invokeLater 和invokeAndWait 了解不多。在快速阅读完整个 EDT 内容后,我可以选择做两件事中的一件。 1 - 使用 Timer 将我的动画一次移动一个像素调用 repaint () 方法。 2 - 使用实现 Runnable 的类创建动画,并使用 invokeAndWait 运行动画。你会推荐哪一个?
  • 如果它是一个恒定、流畅的动画,那么计时器将是一种非常简单的方法,听起来它应该适用于您所描述的内容。您通常不希望在 invokeAndWait 中执行长时间运行的动画,因为这会锁定事件调度线程直到完成,并且在动画完成之前无法处理其他用户界面(例如,鼠标事件)(当然,除非是你想要的)。
  • 是的,我很快就编写了一些代码,看来我将使用定时器!感谢您的帮助杰夫。
  • @Jimmy,没问题。很高兴能提供帮助。
【解决方案2】:

虽然了解 EDT 和 SwingUtilities 很好(每个从事 Swing 的人都应该这样做),但如果您要制作大量动画,我建议您使用 TimingFramework。这将使您能够更专注于设计,并让您更好地控制“速率”。计时框架本质上使用 Swing 计时器,因此回调在 EDT 上。污富客户端合集的一部分,作者发了chapter available。

玩得开心!

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 2015-06-17
    • 1970-01-01
    • 2012-02-05
    • 2012-04-24
    • 2011-05-14
    • 1970-01-01
    • 2014-03-31
    • 2014-04-20
    相关资源
    最近更新 更多