簡體   English   中英

JavaFX一對一顯示多個GIF

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM