You can just copy the value of readln2
into a final
variable:
final String labelText = readln2 ;
Button button = new Button("Click the Button");
button.setOnAction(e -> l.setText(labelText));
If you want to grab a new random line each time, you can either cache the lines of interest and select a random one in the event handler:
Button button = new Button("Click the button");
Label l = new Label();
try {
List<String> lines = Files.lines(Paths.get("/temp/mantra.txt"))
.skip(low)
.limit(high - low)
.collect(Collectors.toList());
Random rng = new Random();
button.setOnAction(evt -> l.setText(lines.get(rng.nextInt(lines.size()))));
} catch (IOException exc) {
exc.printStackTrace();
}
// ...
Or you could just re-read the file in the event handler. The first technique is (much) faster but could consume a lot of memory; the second doesn’t store any of the file contents in memory but reads a file each time the button is pressed, which could make the UI unresponsive.
The error you got basically tells you what was wrong: the only local variables you can access from inside a lambda expression are either final
(declared final
, which means they must be assigned a value exactly once) or “effectively final” (which basically means you could make them final without any other changes to the code).
Your code fails to compile because readln2
is assigned a value multiple times (inside a loop), so it cannot be declared final
. Thus you can’t access it in a lambda expression. In the code above, the only variables accessed in the lambda are l
, lines
, and rng
, which are all “effectively final` as they are assigned a value exactly once. (You can declare them final and the code would still compile.)