Java:使用 Swing 制作安全动画
我正在创建一个使用 JFrame、JPanel、JLabel 和所有其他类型的摆动组件的程序.
I am creating a program that uses JFrame, JPanel, JLabel and all other sorts of swing components.
我想做的是在专门用于此动画的单独 JPanel 上创建 2D 动画.所以我将覆盖paintComponent (Graphics g) 方法.
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.
我有使用 for 循环 + 线程制作动画的经验,但我听说使用 swing 线程不安全.
I have experience making animations with for loops + Threads, but I am hearing that threads are not safe with swing.
因此,使用 Runnable 接口制作动画对我来说安全吗?如果不是我应该使用什么(例如计时器),请举一个小例子说明如何最好地使用它(或网页链接).
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).
感谢 Jeff,我将使用 Timer 来创建动画.对于这个问题的未来观众,这是我在大约 5 分钟内编写的一个快速程序,请原谅脏代码.
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.
我还添加了一些快速评论.
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.
}
}
推荐答案
Jimmy,我认为你误解了 Swing 中线程的工作方式.您必须使用称为 Event Dispatch Thread 的特定线程来对 swing 组件进行任何更新(除了一些特定的例外情况,我不会在此讨论).您可以使用摆动计时器来设置循环任务以在事件调度线程上运行.请参阅如何使用 Swing 计时器的示例.http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html
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
您还应该阅读 Event Dispatch Thread 以便了解它在 Swing 中的位置 http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.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
Java 还在 SwingUtilities
类中提供了多种使用 Swing 的方法,特别是 invokeLater
和 invokeAndWait
,它们将在事件调度线程.
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.
相关文章