Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
155 views
in Technique[技术] by (71.8m points)

java - Timing with Swing animation

i have some problems with Swing and animate a character, I Have a JFrame with key listener and when the user hit down,it calls my JPanel method here

for(int i=1;i<4;i++)
{           
    pY+=16;
    g.drawImage(perso,pX,pY,pX+50,pY+50,0+50*i,0,50+50*i,50,this 
    this.repaint();                 
}

This animate my character but so fast that we can see a thing,how do i can do to view the animation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The answer is already given by Jonas (use a Swing timer), but it might be useful to explain why you are not seeing the animation, and why the timer is the best solution for this problem.

Why do I not see the different repaints

When you call JComponent#repaint the JComponent is not repainted. Instead, an asynchronous request to repaint a certain component is scheduled on the EDT. If you invoke many repaint calls, Swing might decide to group those requests and repaint the component just once.

I did not immediately found an official reference for this in the Oracle documentation (the Swing painting article does not seem to mention it). The only place where I found this was in a note in this article, but I am pretty certain this is documented somewhere.

Why is using a Timer the best solution

For an animation, you basically want to say:

my character should move x pixels in y milliseconds

And preferably, you want to have a smooth animation on screen so you need to repaint rather frequently. If you keep in mind that

  • All interaction with the Swing components should happen on the EDT (Event Dispatch Thread, see the Concurrency in Swing article for more info)
  • You should never block the EDT as this will freeze your UI, meaning you cannot 'wait' in the EDT until a repaint is done or the repaint will never happen
  • Repaint requests can be grouped, so calling repaint x times does not guarantee you that your paint method is called x times as well

The solution to overcome this limitations is to use a Timer. With the same example (moving a character on screen), you can use a Timer to update the position of the character and schedule a repaint. Since the Timer code is triggered on the EDT, you do not violate the Swing threading rules.

In the paintComponent method of your component, you then paint the character at the current location. This might be the 'previous location + 1', or the 'previous location +2' (or ...) depending on how many times the Timer has been triggered between the previous paint call and the current paint call. This ensures the speed at which your character moves is system-independent. Only the smoothness of the animation will depend on your system (as in: how many repaint requests get grouped).

The Swing Timer tutorial to which Jonas already linked contains more information.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...