gpt4 book ai didi

JavaFX 一张一张显示多个gif

转载 作者:行者123 更新时间:2023-12-02 10:05:48 25 4
gpt4 key购买 nike

我想依次显示不同的 gif。
我的想法是使用时间轴动态更改显示包含在图像中的 gif。
但我得到了一个错误:

local variables referenced from a lambda expression must be final or effectively final

有什么解决办法吗?
我的代码:

public class Task10 extends Application {
@Override
public void start(Stage primaryStage) {
HBox hbox5 = new HBox();

VBox VBoxAll = new VBox();


Image gifs[] = new Image[3];
gifs[0] = new Image(this.getClass().getResource("/img/L1.gif").toExternalForm());
gifs[1] = new Image(this.getClass().getResource("/img/L2.gif").toExternalForm());
gifs[2] = new Image(this.getClass().getResource("/img/L1.gif").toExternalForm());

ImageView currentGif = new ImageView();


Button localLoadButton = new Button("Start!");
localLoadButton.setOnAction(e -> {
show(currentGif, gifs);
});

hbox5.getChildren().addAll(currentGif, localLoadButton);

VBoxAll.getChildren().addAll(hbox5);
VBoxAll.setSpacing(15);

Pane pane = new Pane();
pane.getChildren().add(VBoxAll);

Scene scene = new Scene(pane, 500, 350);
primaryStage.setScene(scene);
primaryStage.show();
}

public void show(ImageView currentGif, Image[] gifs) {
for (int i = 0; i<gifs.length; i++) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, e -> { currentGif.setImage(gifs[i]); }),
new KeyFrame(Duration.seconds(2), e -> { currentGif.setImage(null); })
);
timeline.play();
}

}


}

最佳答案

在 Java 中,在 lambda 或匿名类外部声明但在所述 lambda 或匿名类内使用的局部变量必须是“有效的最终变量”。这意味着局部变量永远不会被修改(即重新分配)。如果局部变量可以将 final 关键字添加到声明中而不会导致编译错误,则该变量实际上是最终变量。

在您的代码中,您有以下内容:

public void show(ImageView currentGif, Image[] gifs) {
for (int i = 0; i<gifs.length; i++) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, e -> { currentGif.setImage(gifs[i]); }),
new KeyFrame(Duration.seconds(2), e -> { currentGif.setImage(null); })
);
timeline.play();
}

}

您正在 lambda 内引用局部变量 i(第一个 KeyFrame)。问题是 for 循环修改了 i (例如 i++),这意味着该变量实际上不是最终变量。一个可能的解决方法是在循环内声明另一个变量,为其分配 i 的值,然后在 lambda 内使用该新的(不变!)变量。然而,这并不是唯一的问题。

您的代码正在为 gifs 数组中的每个元素创建一个单独的 Timeline,换句话说,每个循环一个。您还可以在每次迭代结束时在每个 Timeline 上调用 play。这将导致多个Timeline同时播放。正如您可能想象的那样,这不会达到您想要的效果。相反,您应该创建一个单个 Timeline 并将Image 的每次更改作为它自己的KeyFrame。类似于以下内容:

public void show(ImageView view, Image[] gifs, Duration displayDuration) {
Timeline timeline = new Timeline();

Duration totalDelay = Duration.ZERO;
for (Image gif : gifs) {
KeyFrame frame = new KeyFrame(totalDelay, e -> view.setImage(gif));
timeline.getFrames().add(frame);
totalDelay = totalDelay.add(displayDuration);
}
timeline.getFrames().add(new KeyFrame(totalDelay, e -> view.setImage(null));

timeline.play();
}

这会将 Image 更改为数组中以 displayDuration 间隔的下一个 Image

如果您想知道为什么允许在 lambda 内部使用 gif(尽管显然已被修改),这是因为我使用了“增强的 for 循环”。增强型 for 循环的变量处理方式与常规 for 循环不同,因为它在每次迭代时都会初始化。请参阅Enhanced 'for' loop and lambda expressions了解更多信息。

关于JavaFX 一张一张显示多个gif,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55342542/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com