В Java локальные переменные, которые объявлены вне лямбда или анонимного класса, но используются внутри упомянутого лямбда или анонимного класса, должны быть "эффективно финальными".Это означает, что локальная переменная никогда не изменяется (т. Е. Переназначается).Если локальная переменная может иметь ключевое слово 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();
}
}
Вы ссылаетесь на локальную переменную i
внутри лямбды (сначала KeyFrame
).Проблема в том, что цикл for
изменяет i
(например, i++
), что означает, что переменная не является окончательной.Возможное исправление - объявить другую переменную внутри цикла, присвоить ей значение i
, а затем использовать эту новую (неизменную!) Переменную внутри лямбды.Однако это не единственная проблема.
Ваш код создает отдельный Timeline
для каждого элемента в массиве gifs
, другими словами, по одному на цикл.Вы также вызываете play
для каждого Timeline
в конце каждой итерации.Это приведет к одновременному воспроизведению нескольких 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
на следующий Image
в массиве с интервалами displayDuration
.
Если вам интересно, почему gif
разрешено использовать внутри лямбда - несмотря на то, что он, видимо, был модифицирован - это потому, что я использовал «расширенный цикл».Переменная расширенного цикла for обрабатывается иначе, чем обычный цикл for
, поскольку она инициализируется каждую итерацию.См. Расширенные выражения для цикла и лямбда-выражения для получения дополнительной информации.