JavaFX: AnimationTimer. Kontrolowanie czasu trwania i liczby ramek
Klasa Listing14c_04a
Ściągnij klasę Listing14c_04a
Sprawdzamy ile czasu trwa animacja, w której nie kontrolujemy czasu trwania ani liczby ramek.
package rozdzial14c; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import java.time.Duration; import java.time.Instant; public class Listing14c_04a extends Application { private double radius = 10.0; private Circle circle; private Instant start; @Override public void start(Stage stage) { StackPane root = new StackPane(); circle = new Circle(radius); circle.setFill(Color.DARKCYAN); root.getChildren().add(circle); AnimationTimer timer = new MyTimer(); timer.start(); start=Instant.now(); Scene scene = new Scene(root, 300, 300); stage.setTitle("AnimationTimer"); stage.setScene(scene); stage.show(); } private class MyTimer extends AnimationTimer { @Override public void handle(long now) { System.out.println(now); radius += 0.5; circle.radiusProperty().set(radius); if (radius >= 80.0) { radius = 10.0; circle.radiusProperty().set(radius); stop(); Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println("Czas trwania: "+ millis); } } } public static void main(String[] args) { Application.launch(args); } }
Po uruchomieniu klasy, uruchomieniu i zatrzymaniu stopera zobaczymy przeskakujące nanoczasy oraz wynik:
10254468416861 10254484909798 10254532553914 10254548911015 10254564971088 10254580917359 10254596908004 10254612922496 10254628917366 10254644908313 10254660930049 10254676902583 10254692904698 10254708908323 10254724963263 10254740927646 10254756933082 10254772933688 10254788918900 10254804931882 10254820884493 10254836928868 10254852897779 10254868900499 10254884910764 10254900933406 10254916918014 10254949011293 10254964967827 10254980973263 10254996959380 10255012983531 10255028998325 10255044964217 10255060939165 10255076943696 10255092972676 10255109004676 10255124962116 10255140998342 10255156964536 10255172941295 10255190000821 10255204901455 10255220918965 10255236896932 10255252974512 10255268995946 10255284960329 10255300930448 10255316918980 10255348978450 10255365012865 10255380954307 10255396953705 10255412987214 10255429006233 10255445002312 10255461007446 10255477352170 10255492992660 10255508989643 10255525026171 10255540982705 10255556996895 10255573010783 10255588961281 10255604981206 10255620938344 10255636930197 10255652930803 10255668967028 10255684953145 10255700929603 10255717040085 10255748990887 10255764996323 10255781032850 10255797203101 10255813750070 10255829002672 10255844958905 10255860966152 10255876960117 10255893044941 10255908990006 10255924990310 10255941007820 10255957010841 10255973058839 10255989002696 10256004961947 10256020988513 10256036939916 10256052967388 10256069007839 10256084971619 10256100930267 10256132980380 10256149057054 10256165059472 10256181028383 10256197054345 10256213021747 10256229035031 10256245012092 10256261040771 10256276997909 10256292978895 10256308989764 10256324988559 10256341027199 10256357013618 10256373009395 10256388999134 10256405007588 10256420971669 10256436940279 10256453048044 10256468962621 10256485016958 10256500937572 10256532997948 10256549073717 10256565015461 10256580982862 10256596978941 10256613027240 10256628998868 10256645018491 10256661030266 10256677047475 10256693100906 10256709055630 10256725065895 10256741064086 10256757039638 10256773046583 10256788992855 10256805059568 Czas trwania: 2497
Klasa Listing14c_04b
Ściągnij klasę Listing14c_04b
Kontrolujemy czas trwania animacji. Kontrolujemy płynność animacji rozszerzając klasę Interpolator
.
package rozdzial14c; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import java.time.Duration; import java.time.Instant; public class Listing14c_04b extends Application { private double radius; private Circle circle; private long duration; private Linear interp; @Override public void start(Stage stage) { StackPane root = new StackPane(); circle = new Circle(radius); duration = 2000;//ms circle.setFill(Color.DARKCYAN); interp = new Linear(); root.getChildren().add(circle); AnimationTimer timer = new MyTimer(); timer.start(); Scene scene = new Scene(root, 300, 300); stage.setTitle("AnimationTimer"); stage.setScene(scene); stage.show(); } private class MyTimer extends AnimationTimer { Instant start = Instant.now(); @Override public void handle(long now) { long elapsed = Duration.between(start, Instant.now()).toMillis(); if(elapsed <= duration) { double radiusStart = 10.0; double radiusEnd = 80; double r = interp.interpolate(radiusStart, radiusEnd, (double) elapsed / (double) duration); circle.radiusProperty().set(r); }else{ radius = 10.0; circle.radiusProperty().set(radius); stop(); Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println("Czas trwania: "+ millis); } } } public static void main(String[] args) { Application.launch(args); } }
Klasa Linear
Ściągnij klasę Linear.zip
package rozdzial14c; import javafx.animation.Interpolator; public class Linear extends Interpolator { @Override protected double curve(double v) { return v; } }
Po uruchomieniu klasy Listing_14c_04b na konsoli zobaczymy:
Czas trwania: 2015
Klasa Listing14_35c
Ściągnij klasę Listing14c_04c
Kontrolujemy czas trwania aplikacji. Ograniczamy liczbę ramek przez zastosowanie Thread.sleep()
.
package rozdzial14c; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import java.time.Duration; import java.time.Instant; public class Listing14c_04c extends Application { private double radius; private Circle circle; private long duration; private Linear interp; @Override public void start(Stage stage) { StackPane root = new StackPane(); circle = new Circle(radius); duration = 2000;//ms circle.setFill(Color.DARKCYAN); interp = new Linear(); root.getChildren().add(circle); AnimationTimer timer = new MyTimer(); timer.start(); Scene scene = new Scene(root, 300, 300); stage.setTitle("AnimationTimer"); stage.setScene(scene); stage.show(); } private class MyTimer extends AnimationTimer { Instant start = Instant.now(); int counter = 0; @Override public void handle(long now) { long elapsed = Duration.between(start, Instant.now()).toMillis(); counter++; if(elapsed <= duration) { double radiusStart = 10.0; double radiusEnd = 80; double r = interp.interpolate(radiusStart, radiusEnd, (double) elapsed / (double) duration); circle.radiusProperty().set(r); try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } }else{ radius = 10.0; circle.radiusProperty().set(radius); stop(); Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println("Czas trwania: "+ millis); System.out.println("Counter: "+ counter); } } } public static void main(String[] args) { Application.launch(args); } }
Po uruchomieniu klasy na konsoli zobaczymy:
Czas trwania: 2020 Counter: 56
Klasa Listing14c_04d
Ściągnij klasę Listing14c_04d
Sprawdzamy poprzednie rozwiązanie przedłużając 2× czas trwania animacji. Używamy pomiarów
wykorzystując System.nanotime()
.
package rozdzial14c; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import java.time.Duration; import java.time.Instant; import java.util.concurrent.TimeUnit; public class Listing14c_04d extends Application { private double radius; private Circle circle; private long duration; private Linear interp; @Override public void start(Stage stage) { StackPane root = new StackPane(); circle = new Circle(radius); duration = 4000;//ms circle.setFill(Color.DARKCYAN); interp = new Linear(); root.getChildren().add(circle); AnimationTimer timer = new MyTimer(); timer.start(); Scene scene = new Scene(root, 300, 300); stage.setTitle("AnimationTimer"); stage.setScene(scene); stage.show(); } private class MyTimer extends AnimationTimer { Instant start = Instant.now(); long start2 = System.nanoTime(); int counter = 0; @Override public void handle(long now) { long elapsed1 = now - start2; long elapsed2 = TimeUnit.MILLISECONDS.convert(elapsed1, TimeUnit.NANOSECONDS); counter++; if(elapsed2 <= duration) { double radiusStart = 10.0; double radiusEnd = 80; double r = interp.interpolate(radiusStart, radiusEnd, (double) elapsed2 / (double) duration); circle.radiusProperty().set(r); try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } }else{ radius = 10.0; circle.radiusProperty().set(radius); stop(); Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println("Czas trwania: "+ millis); System.out.println("Counter: "+ counter); } } } public static void main(String[] args) { Application.launch(args); } }
Po uruchomieniu otrzymujemy na konsoli>
Czas trwania: 4007 Counter: 116
Jak widzimy czas trwania animacji wzrósł dwukrotnie podobnie jak liczba klatek animacji.
W ten sposób osiągnęliśmy to o co nam chodziło.