[英]JavaFX display multiple gifs one by one
我想一個接一個地顯示不同的gif。
我的想法是使用時間軸動態更改包裝到圖像中的顯示gif。
但我得到一個錯誤:
從lambda表達式引用的局部變量必須是final或有效的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
關鍵字而不引起編譯錯誤,則該變量實際上是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(第一個KeyFrame
)內部引用局部變量i
。 問題是for
循環修改了i
(例如i++
),這意味着變量實際上不是最終值。 可能的解決方法是在循環內聲明另一個變量,為其分配i
值,然后在lambda內使用該新變量(不變!)。 但是,這不是唯一的問題。
您的代碼正在為gifs
數組中的每個元素創建單獨的Timeline
,換句話說,每個循環一個。 您還play
在每次迭代結束時在每個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();
}
這將以displayDuration
間隔將Image
更改為數組中的下一個Image
。
如果您想知道為什么允許在lambda中使用gif
(盡管顯然已被修改),這是因為我使用了“增強的for循環”。 增強型for循環的變量與常規for
循環的區別在於每次迭代都會對其進行初始化 。 有關更多信息,請參見增強的“ for”循環和lambda表達式 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.