如何在 JavaFX 中停止动画 GIF?
How I can stop an animated GIF in JavaFX?
我想在我的项目中使用动画 GIF,但我不知道如何停止循环动画。我的意思是,我希望 GIF 只播放 1 次。
谢谢!
我没有做过 GIF 动画,甚至不知道 JavaFX 会有启动和停止它们的方法。如果您想使用图像制作任何动画,我建议您自己逐帧制作。这样你就可以完全控制它,你的图像中可以有超过 256 种颜色。
我在 Mike 的博客中阅读了一篇关于 Creating a Sprite Animation with JavaFX 的非常好的文章。
这很容易做到。您只需扩展 Transition class, add an ImageView to it and implement the Transition's Interpolate method.
编辑:哦,顺便说一句,GIF 有一个循环标志,告诉它们循环播放或不循环播放。换句话说:理论上您可以修改 GIF 文件的循环 属性。仅在理论上,因为我只是尝试指定只播放一次,而在 JavaFX 中它仍然无限循环播放,而在 FireFox 中它只播放一次。顺便说一下,JavaFX 似乎不支持支持超过 256 种颜色的动画 PNG (APNG)。所以自动图像动画功能非常有限。最好自己做动画。
我希望有人想出更好的东西,但这里有一个示例代码,说明您如何可以完全控制您的 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;
}
}
}
它提供了一个pause/resume按钮用于测试。你还需要的是 Gif Decoder code and an animated banana.gif.
我想在我的项目中使用动画 GIF,但我不知道如何停止循环动画。我的意思是,我希望 GIF 只播放 1 次。
谢谢!
我没有做过 GIF 动画,甚至不知道 JavaFX 会有启动和停止它们的方法。如果您想使用图像制作任何动画,我建议您自己逐帧制作。这样你就可以完全控制它,你的图像中可以有超过 256 种颜色。
我在 Mike 的博客中阅读了一篇关于 Creating a Sprite Animation with JavaFX 的非常好的文章。
这很容易做到。您只需扩展 Transition class, add an ImageView to it and implement the Transition's Interpolate method.
编辑:哦,顺便说一句,GIF 有一个循环标志,告诉它们循环播放或不循环播放。换句话说:理论上您可以修改 GIF 文件的循环 属性。仅在理论上,因为我只是尝试指定只播放一次,而在 JavaFX 中它仍然无限循环播放,而在 FireFox 中它只播放一次。顺便说一下,JavaFX 似乎不支持支持超过 256 种颜色的动画 PNG (APNG)。所以自动图像动画功能非常有限。最好自己做动画。
我希望有人想出更好的东西,但这里有一个示例代码,说明您如何可以完全控制您的 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;
}
}
}
它提供了一个pause/resume按钮用于测试。你还需要的是 Gif Decoder code and an animated banana.gif.