I use AnimationTimer
for several tasks like animation with changing pictures and ProgressIndicator
animation. To achieve needed speed I put thread to sleep, but when several animations are running simultaneously they affect each others speed. Is there any other way to change speed of AnimationTimer
? Code sample:
private void initialize() {
programButtonAnimation=new AnimationTimer(){
@Override
public void handle(long now) {
showClockAnimation();
}
};
programButtonAnimation.start();
}
private void showClockAnimation(){
String imageName = "%s_"+"%05d"+".%s";
String picturePath="t093760/diploma/view/styles/images/pink_frames/"+String.format( imageName,"pink" ,frameCount,"png");
programButton.setStyle("-fx-background-image:url('"+picturePath+"')");
frameCount++;
try {
Thread.sleep(28);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(frameCount>=120){
programButtonAnimation.stop();
frameCount=0;
}
}
The AnimationTimer
's handle
method is invoked once for each frame that is rendered, on the FX Application Thread. You should never block that thread, so do not call Thread.sleep(...)
here.
The parameter passed to the handle(...)
method is a timestamp, in nanoseconds. So if you want to throttle updates so they don't happen more than once every, say 28 milliseconds, you can use this to do so:
private void initialize() {
programButtonAnimation=new AnimationTimer(){
private long lastUpdate = 0 ;
@Override
public void handle(long now) {
if (now - lastUpdate >= 28_000_000) {
showClockAnimation();
lastUpdate = now ;
}
}
};
programButtonAnimation.start();
}
private void showClockAnimation(){
String imageName = "%s_"+"%05d"+".%s";
String picturePath="t093760/diploma/view/styles/images/pink_frames/"+String.format( imageName,"pink" ,frameCount,"png");
programButton.setStyle("-fx-background-image:url('"+picturePath+"')");
frameCount++;
if(frameCount>=120){
programButtonAnimation.stop();
frameCount=0;
}
}
Since I already wrote the code and James_D was faster with informing you about you blocking the UI, I still like to add that if you have multiple AnimationTimers of different timings you should create a dedicated class for that. If each of them runs at a different speed, you could implement it like that:
import javafx.animation.AnimationTimer;
public abstract class AnimationTimerExt extends AnimationTimer {
private long sleepNs = 0;
long prevTime = 0;
public AnimationTimerExt( long sleepMs) {
this.sleepNs = sleepMs * 1_000_000;
}
@Override
public void handle(long now) {
// some delay
if ((now - prevTime) < sleepNs) {
return;
}
prevTime = now;
handle();
}
public abstract void handle();
}
Which means that the handle() method is invoked at least after sleepMs milliseconds have passed.
Or you change the parameter and specify the fps, whatever you need.
You can use the above code like this:
AnimationTimerExt timer = new AnimationTimerExt(100) {
@Override
public void handle() {
System.out.println( System.currentTimeMillis());
}
};
timer.start();
Also, loading the picture over and over again is not the best choice. If you'd like to do animations, I suggest you take a look at Mike's Blog about Creating a Sprite Animation with JavaFX.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With