如何在 JavaFX 中使用时间轴更改图像
How to change images with Timeline in JavaFX
我打算通过将 for 循环中的关键帧添加到时间轴对象来随时间改变鸟类的图像。原来只显示了第一张图片。有人可以指出我在哪里弄错了。提前致谢。
此外,我注意到我必须在 for 循环后将计数器 "index" 重置为 0,否则它会生成 java.lang.ArrayIndexOutOfBoundsException。
打包申请;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
public class Main extends Application
{
int index=0;
@Override
public void start(Stage primaryStage) {
try {
ImageView bgV = new ImageView();
Image img_BG = new Image(Main.class.getResourceAsStream("background.png"));
bgV.setImage(img_BG);
bgV.setEffect(new BoxBlur());
bgV.setOpacity(0.5);
ImageView t1V = new ImageView();
Image img_t1 = new Image(Main.class.getResourceAsStream(
"t1.png"
));
t1V.setImage(img_t1);
ImageView t2V = new ImageView();
Image img_t2 = new Image(Main.class.getResourceAsStream(
"t2.png"
));
t2V.setImage(img_t2);
ImageView t3V = new ImageView();
Image img_t3 = new Image(Main.class.getResourceAsStream(
"t3.png"
));
t3V.setImage(img_t3);
Group foreground = new Group(t1V,t2V,t3V);
t1V.setTranslateX(20);
t1V.setTranslateY(200);
t2V.setTranslateX(300);
t2V.setTranslateY(200);
t3V.setTranslateX(550);
t3V.setTranslateY(200);
foreground.setEffect(new DropShadow());
String[]
birdFiles = {"b1.png", "b2.png", "b3.png", "b4.png", "b5.png", "b6.png"};
double[] ds = { 300, 600, 900, 1200, 1500, 1800};
ImageView birdV = new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[0])));
Group birds = new Group(birdV);
birds.setTranslateX(img_BG.getWidth()-100);
Timeline timeline = new Timeline();
timeline.setCycleCount(
Animation.INDEFINITE
);
KeyFrame[] kframs = new KeyFrame[birdFiles.length];
for( index=0; index<birdFiles.length; index++)
{
EventHandler<ActionEvent>
onFishined = new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent arg0)
{
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[index]))));
}
};
Duration duration = Duration.millis(ds[index]);
KeyFrame
kf = new KeyFrame(duration, onFishined,null,null );
timeline.getKeyFrames().add(kf);
}//End for i
index = 0;
timeline.play();
Group root = new Group(bgV,foreground,birds);
Scene scene = new Scene(root,img_BG.getWidth(), img_BG.getHeight());
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
您不必在外部声明您的 index
字段。这也会导致您的问题:每当调用 handle
方法时,它都会引用您的字段:index
,您在循环后将其设置为 0。
因此您可以将新字段声明为 final
并将其传递给处理程序:
for (int index = 0; index < birdFiles.length; index++) {
final int birdIndex = index;
EventHandler<ActionEvent> onFishined = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[birdIndex]))));
}
};
...
}
我打算通过将 for 循环中的关键帧添加到时间轴对象来随时间改变鸟类的图像。原来只显示了第一张图片。有人可以指出我在哪里弄错了。提前致谢。
此外,我注意到我必须在 for 循环后将计数器 "index" 重置为 0,否则它会生成 java.lang.ArrayIndexOutOfBoundsException。
打包申请;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
public class Main extends Application
{
int index=0;
@Override
public void start(Stage primaryStage) {
try {
ImageView bgV = new ImageView();
Image img_BG = new Image(Main.class.getResourceAsStream("background.png"));
bgV.setImage(img_BG);
bgV.setEffect(new BoxBlur());
bgV.setOpacity(0.5);
ImageView t1V = new ImageView();
Image img_t1 = new Image(Main.class.getResourceAsStream(
"t1.png"
));
t1V.setImage(img_t1);
ImageView t2V = new ImageView();
Image img_t2 = new Image(Main.class.getResourceAsStream(
"t2.png"
));
t2V.setImage(img_t2);
ImageView t3V = new ImageView();
Image img_t3 = new Image(Main.class.getResourceAsStream(
"t3.png"
));
t3V.setImage(img_t3);
Group foreground = new Group(t1V,t2V,t3V);
t1V.setTranslateX(20);
t1V.setTranslateY(200);
t2V.setTranslateX(300);
t2V.setTranslateY(200);
t3V.setTranslateX(550);
t3V.setTranslateY(200);
foreground.setEffect(new DropShadow());
String[]
birdFiles = {"b1.png", "b2.png", "b3.png", "b4.png", "b5.png", "b6.png"};
double[] ds = { 300, 600, 900, 1200, 1500, 1800};
ImageView birdV = new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[0])));
Group birds = new Group(birdV);
birds.setTranslateX(img_BG.getWidth()-100);
Timeline timeline = new Timeline();
timeline.setCycleCount(
Animation.INDEFINITE
);
KeyFrame[] kframs = new KeyFrame[birdFiles.length];
for( index=0; index<birdFiles.length; index++)
{
EventHandler<ActionEvent>
onFishined = new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent arg0)
{
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[index]))));
}
};
Duration duration = Duration.millis(ds[index]);
KeyFrame
kf = new KeyFrame(duration, onFishined,null,null );
timeline.getKeyFrames().add(kf);
}//End for i
index = 0;
timeline.play();
Group root = new Group(bgV,foreground,birds);
Scene scene = new Scene(root,img_BG.getWidth(), img_BG.getHeight());
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
您不必在外部声明您的 index
字段。这也会导致您的问题:每当调用 handle
方法时,它都会引用您的字段:index
,您在循环后将其设置为 0。
因此您可以将新字段声明为 final
并将其传递给处理程序:
for (int index = 0; index < birdFiles.length; index++) {
final int birdIndex = index;
EventHandler<ActionEvent> onFishined = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[birdIndex]))));
}
};
...
}