Java:使用 Swing 的安全动画

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6273581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:09:22  来源:igfitidea点击:

Java: Safe Animations with Swing

javaswinganimationjframe

提问by Jimmy Huch

I am creating a program that uses JFrame, JPanel, JLabel and all other sorts of swing components.

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

What I want to do is create a 2D animation on a separate JPanel that is dedicated to this animation. So I will be overriding the paintComponent (Graphics g) method.

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

I have experience making animations with for loops + Threads, but I am hearing that threads are not safe with swing.

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

Due to this, is it safe for me to make an animation with the use of the Runnable interface? If not what shall I use (e.g. Timer) and please give a small example on how to best use it (or a link to a web page).

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

EDIT:

编辑:

Thanks to Jeff, I will be using Timer to create the animation. For future viewers of this question, here is a quick program I coded in about 5 minutes, excuse the dirty code.

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

I have also added some quick comments.

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

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

回答by Jeff Storey

Jimmy, I think you are misunderstanding how threads work in Swing. You must use a specific thread called the Event Dispatch Thread to do any updating on swing components (with a few specific exceptions I won't discuss here). You can use a swing timer to set a recurring task to run on the event dispatch thread. See this example of how to use Swing timers. http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html

Jimmy,我认为您误解了线程在 Swing 中的工作方式。您必须使用一个名为 Event Dispatch Thread 的特定线程来对 Swing 组件进行任何更新(除了一些特定的例外,我不会在这里讨论)。您可以使用摆动计时器设置在事件调度线程上运行的重复任务。请参阅此示例了解如何使用 Swing 计时器。http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html

You should also read up on the Event Dispatch Thread so you understand its place in Swing http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

您还应该阅读事件调度线程,以便了解它在 Swing 中的位置http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

Java also provides a variety of methods for working with Swing in the SwingUtilitiesclass, notably invokeLaterand invokeAndWaitwhich will run code on the event dispatch thread.

Java也提供了多种方法用于与Swing合作的SwingUtilities类,特别是invokeLaterinvokeAndWait这将运行事件调度线程上的代码。

回答by Windust

While is good to understand the EDT and SwingUtilities (everybody doing Swing should do so) if you're going to be doing a lot of animation I would recommend to use the TimingFramework. This will allow you to concentrate a little more on design and will give you a better control on "rate". Inherently the timing framework uses a Swing timer so the callbacks are on the EDT. Part of the Filthy-rich clients collection, the author made the chapter available.

如果您要制作大量动画,那么了解 EDT 和 SwingUtilities 很好(每个使用 Swing 的人都应该这样做),但我建议您使用TimingFramework。这将使您更专注于设计,并让您更好地控制“速率”。本质上,计时框架使用 Swing 计时器,因此回调位于 EDT 上。作为 Filthy-rich clients 集合的一部分,作者提供了该章节

Have fun!

玩得开心!