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
Java: Safe Animations with Swing
提问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 SwingUtilities
class, notably invokeLater
and invokeAndWait
which will run code on the event dispatch thread.
Java也提供了多种方法用于与Swing合作的SwingUtilities
类,特别是invokeLater
和invokeAndWait
这将运行事件调度线程上的代码。
回答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!
玩得开心!