我要一个接一个地显示不同的gif。
我的想法是使用时间轴动态更改包装在图像中的显示gif。
但是我遇到了一个错误:
从Lambda表达式引用的局部变量必须是final或 有效地最终
有什么解决办法吗?
我的代码:
10000000
答案 0 :(得分:1)
在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内使用该新变量(不变!)。但是,这不是唯一的问题。
您的代码正在为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
在lambda中使用(尽管显然已被修改),这是因为我使用了“增强的循环”。与常规for
循环相比,增强型for循环的变量与常规[]
循环的区别在于每次迭代 initialized 。有关更多信息,请参见Enhanced 'for' loop and lambda expressions。