Как я могу остановить анимированный GIF в JavaFX?

Я хочу использовать анимированный GIF в своем проекте, но я не знаю, как я могу остановить цикл анимации. Я хочу, чтобы GIF играл только 1 раз.

Спасибо!

1 ответ

Решение

Я не делал анимацию в формате GIF, даже не знал, что в JavaFX будут методы для их запуска и остановки. Если вы хотите сделать ЛЮБУЮ анимацию, используя изображения, я бы посоветовал вам делать это кадр за кадром самостоятельно. Таким образом, вы имеете полный контроль над ним, и вы можете иметь более 256 цветов на вашем изображении.

Я прочитал очень хорошую статью о создании спрайтовой анимации с помощью JavaFX в блоге Майка.

Это очень легко сделать. Вы просто расширяете класс Transition, добавляете к нему ImageView и внедряете метод Interpolate для Transition.

Edit: о, и, кстати, GIF-файлы имеют флаг цикла, который говорит им, чтобы проигрывать в цикле или не воспроизводить в цикле. Другими словами: теоретически вы можете изменить свойство цикла файла GIF. Только в теории, потому что я только что попытался с указанием воспроизведения только один раз, а в JavaFX он все еще воспроизводился в бесконечном цикле, в то время как в FireFox он воспроизводился один раз. Кстати, JavaFX, похоже, не поддерживает анимированные PNG (APNG), которые поддерживают более 256 цветов. Таким образом, возможности автоматической анимации изображения очень ограничены. Лучше всего сделать анимацию самостоятельно.

Я надеюсь, что кто-то придумает что-то лучше, но вот пример кода о том, как вы можете получить полный контроль над своим GIF.

import java.awt.image.BufferedImage;
import java.net.URISyntaxException;

import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * Requires GifDecoder from here: http://www.java2s.com/Code/Java/2D-Graphics-GUI/DecodesaGIFfileintooneormoreframes.htm
 */
public class AnimatedGifDemo extends Application {

    @Override
    public void start(Stage primaryStage) throws URISyntaxException {

        HBox root = new HBox();

        // TODO: provide gif file, ie exchange banana.gif with your file
        Animation ani = new AnimatedGif(getClass().getResource("banana.gif").toExternalForm(), 1000);
        ani.setCycleCount(10);
        ani.play();

        Button btPause = new Button( "Pause");
        btPause.setOnAction( e -> ani.pause());

        Button btResume = new Button( "Resume");
        btResume.setOnAction( e -> ani.play());

        root.getChildren().addAll( ani.getView(), btPause, btResume);

        Scene scene = new Scene(root, 1600, 900);

        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }

    public class AnimatedGif extends Animation {

        public AnimatedGif( String filename, double durationMs) {

            GifDecoder d = new GifDecoder();
            d.read( filename);

            Image[] sequence = new Image[ d.getFrameCount()];
            for( int i=0; i < d.getFrameCount(); i++) {

                WritableImage wimg = null;
                BufferedImage bimg = d.getFrame(i);
                sequence[i] = SwingFXUtils.toFXImage( bimg, wimg);

            }

            super.init( sequence, durationMs);
        }

    }

    public class Animation extends Transition {

        private ImageView imageView;
        private int count;

        private int lastIndex;

        private Image[] sequence;

        private Animation() {
        }

        public Animation( Image[] sequence, double durationMs) {
            init( sequence, durationMs);
        }

        private void init( Image[] sequence, double durationMs) {
            this.imageView = new ImageView(sequence[0]);
            this.sequence = sequence;
            this.count = sequence.length;

            setCycleCount(1);
            setCycleDuration(Duration.millis(durationMs));
            setInterpolator(Interpolator.LINEAR);

        }

        protected void interpolate(double k) {

            final int index = Math.min((int) Math.floor(k * count), count - 1);
            if (index != lastIndex) {
                imageView.setImage(sequence[index]);
                lastIndex = index;
            }

        }

        public ImageView getView() {
            return imageView;
        }

    }

}

Он предоставляет кнопку паузы / возобновления для тестирования. Кроме того, вам нужен код Gif Decoder и анимированный файл banana.gif.

Другие вопросы по тегам