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.)