我该如何在JavaFX中停止动画GIF?

7

我想在我的项目中使用一个动态GIF,但我不知道如何停止循环播放。我的意思是,我希望这个GIF只播放一次。

谢谢!

1个回答

13

我没有做过GIF动画,甚至不知道JavaFX会有启动和停止它们的方法。如果你想使用图片做任何动画,我建议你自己逐帧制作,这样你可以完全控制它,并且图像中可以使用超过256种颜色。

我在Mike的博客上读到了一篇关于使用JavaFX创建精灵动画的很好的文章。

非常容易实现。你只需要扩展Transition类,在其中添加一个ImageView并实现Transition的插值方法

编辑:哦,顺便说一句,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解码器代码 和一个动画banana.gif

输入图像描述


非常感谢Roland,提供了非常有用的信息! - Ezequiel
不用谢。我使用了专门的AnimatedGif类和JavaFX内部的BufferedImage -> Image转换机制更新了代码。 - Roland
我知道这是一个旧帖子,但是 btPause.setOnAction( e -> ani.pause()); 中的 e 是从哪里来的?它似乎是一个神秘的字母,但它确实起作用,我找不到变量 e - user1944429
@sand_storm_of_code.txt 这是一个按钮动作处理程序的 Lambda 版本。其中 e 代表 ActionEvent event 中的 event。基本上,它是示例 3 setOnAction 的简短版本 这里 - SedJ601

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接