JavaFX z Arią - powrót do strony głównej

JavaFX: seryjne migawki (gif) z węzła (Node)

W JavaFX 14 migawki możemy tworzyć ze sceny (Scene), z węzła (Node) oraz z ekranu (Robot).

W tym wpisie pokazuję jak utworzyć i zapisać na dysku seryjne migawki z węzła Node.

Mogą być podstawą do utworzenia animowanego GIF-a, czy innej animacji.

Klasa Listing07c_02

Ściągnij klasę Listing07c_02

package rozdzial07c;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
public class Listing07c_02 extends Application {
    private double radius = 30;
    private int counter;
    private StackPane root;
    private Circle circle;
    private SnapshotParameters params;

    @Override
    public void start(Stage stage) {
        root = new StackPane();
        //-
        counter = 1;
        params = new SnapshotParameters();
        params.setFill(Color.WHITE);
        params.setViewport(new
                Rectangle2D(0, 0, 270, 300));
        //-
        circle = new Circle(radius);
        circle.setFill(Color.DARKCYAN);
        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 {
        @Override
        public void handle(long now) {
            WritableImage wi = root.snapshot(params, null);
            File file = new File(
                    "rozdzial07c/src/rozdzial07c/gifs/rys07_"
                    + leadingZeroes(2, counter) + ".gif");
            BufferedImage bi = SwingFXUtils.fromFXImage(wi,
                    null);
            try {
                ImageIO.write(bi, "gif", file);
                counter++;
                System.out.println(Instant.now());
            } catch (IOException e) {
                e.printStackTrace();
            }
            radius -= 0.5;
            circle.radiusProperty().set(radius);
            if (radius <= 0) {
                radius = 30.0;
                circle.radiusProperty().set(radius);
                stop();
                System.out.println("Animation stopped");
            }
        }
    }
    private static String leadingZeroes(int digits, int number) {
        return String.format("%0" + String.valueOf(digits) + "d", number);
    }
    public static void main(String[] args) {
        Application.launch(args);
    }
}

Automatyczna numeracja gifów stwarza problem. Chociaż numery są po kolei i obrazki w IDE są listowane w prawidłowej kolejności, to po pobraniu obrazków przez klasy Java w celu wykonania animowanego gifa obrazki nie są już ułożone po kolei, np. po 1 następuje 10, 11, …, 2, 21, 22, itd. Aby rozwiązać ten problem trzeba dodać zera wiodące. Czyni to metoda leadingZeroes, w której podajemy maksymalna liczbę cyfr w numerze oraz numer do którego należy dodać zera.

private static String leadingZeroes(int digits, int number) {
        return String.format("%0" + String.valueOf(digits) + "d", number);
    }

Po uruchomieniu klasy w folderze gifs zobaczymy automatycznie wykonane zrzuty ekranu wraz z prawidłowo ponumerowanymi obrazkami.

Przykładowy wygląd zrzutu z węzła (Rys. 07_03):

Widok folderu z gifami (fragment)
Rys. 07_03. Widok folderu z gifami (fragment)

Przykładowy gif (rys07_04):

Migawka z węzła (Node)
Rys. 07_04. Migawka z węzła (Node)

Problemem tej animacji jest oczywiście fakt, że nie kontrolujemy ani liczby ani odstępów czasowych pomiędzy wykonaniem kolejnych migawek. Problem ten rozwiążemy w innym przykładzie.

Na konsoli widzimy czasy pobrania kolejnych migawek.

...
2021-01-08T09:36:37.487456700Z
2021-01-08T09:36:37.510458100Z
2021-01-08T09:36:37.537459600Z
2021-01-08T09:36:37.559460900Z
2021-01-08T09:36:37.588462500Z
2021-01-08T09:36:37.610463800Z
2021-01-08T09:36:37.638465400Z
Animation stopped