Después de buscar en diferentes repositorios y páginas de internet al terminar descubrimos la respuesta que te compartiremos a continuación.
Solución:
Puedes simplemente copiar el valor de readln2
en un final
variable:
final String labelText = readln2 ;
Button button = new Button("Click the Button");
button.setOnAction(e -> l.setText(labelText));
Si desea obtener una nueva línea aleatoria cada vez, puede almacenar en caché las líneas de interés y seleccionar una aleatoria en el controlador de eventos:
Button button = new Button("Click the button");
Label l = new Label();
try
List 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();
// ...
O simplemente puede volver a leer el archivo en el controlador de eventos. La primera técnica es (mucho) más rápida pero podría consumir mucha memoria; el segundo no almacena ninguno de los contenidos del archivo en la memoria, pero lee un archivo cada vez que se presiona el botón, lo que podría hacer que la interfaz de usuario no responda.
El error que recibió básicamente le dice qué estaba mal: las únicas variables locales a las que puede acceder desde dentro de una expresión lambda son final
(declarado final
lo que significa que se les debe asignar un valor exactamente una vez) o “efectivamente definitivos” (lo que básicamente significa que puede hacerlos definitivos sin ningún otro cambio en el código).
Su código no se compila porque readln2
se le asigna un valor varias veces (dentro de un bucle), por lo que no se puede declarar final
. Por lo tanto, no puede acceder a él en una expresión lambda. En el código anterior, las únicas variables a las que se accede en la lambda son l
, lines
y rng
que son todos “efectivamente finales”, ya que se les asigna un valor exactamente una vez. (Puede declararlos finales y el código aún se compilará).
El error que encontró significa que cada variable a la que accede dentro de un cuerpo de expresiones lambda tiene que ser final o efectivamente final. Para conocer la diferencia, vea esta respuesta aquí: Diferencia entre final y efectivamente final
El problema en tu código es la siguiente variable
String readln2 = null;
La variable se declara y asigna más adelante, el compilador no puede detectar si se asigna una o varias veces, por lo que no es efectivamente final.
La forma más fácil de resolver esto es usar un objeto contenedor, en este caso una propiedad de cadena en lugar de una cadena. Este contenedor se asigna solo una vez y, por lo tanto, es efectivamente definitivo:
StringProperty readln2 = new SimpleStringProperty();
readln2.set(in.readLine());
button.setOnAction(e -> l.setText(readln2.get()));
Acorté el código para mostrar solo las partes relevantes.
Recuerda que te damos el privilegio explicar si te ayudó.