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?
don't extend
JFrame
, createJFrame
as local variabledon't use
KeyListener
, useKeyBindings
insteaddon't paint directly to the
JFrame
, usedrawImage()
to theJLabel
orJComponent/JPanel
another issue with
KeyListener
, you have to set for delay betweens twoKeyEvents
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
theJComponent
is not repainted. Instead, an asynchronous request to repaint a certain component is scheduled on the EDT. If you invoke manyrepaint
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 solutionFor an animation, you basically want to say:
And preferably, you want to have a smooth animation on screen so you need to repaint rather frequently. If you keep in mind that
x
times does not guarantee you that yourpaint
method is calledx
times as wellThe solution to overcome this limitations is to use a
Timer
. With the same example (moving a character on screen), you can use aTimer
to update the position of the character and schedule a repaint. Since theTimer
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 theTimer
has been triggered between the previouspaint
call and the currentpaint
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.You can use a Swing Timer and update the animation in regular intervals. See How to Use Swing Timers