Я предполагаю, так как ваш вопрос неполный, вы по какой-то причине сделали l oop index i
переменной экземпляра. Т.е. у вас есть что-то вроде:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Demo extends Application {
// Guessing:
private int i ;
@Override
public void start(Stage primaryStage) throws Exception {
HBox p1 = new HBox();
RadioButton red = new RadioButton("RED");
RadioButton blue = new RadioButton("Blue");
RadioButton black = new RadioButton("Black");
ToggleGroup tg = new ToggleGroup();
red.setToggleGroup(tg);
blue.setToggleGroup(tg);
black.setToggleGroup(tg);
RadioButton[] array = { red, blue, black };
p1.getChildren().addAll(red, blue, black);
i = 0;
for (i = 0; i < array.length; i++) {
array[i].setOnAction(e -> {
System.out.println(array[i].getText());
});
}
Scene scene = new Scene(p1, 400, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
Здесь i
- это свойство экземпляра Demo
(т. Е. Экземпляра приложения, для которого вызывается start()
). В методе start()
i
инициализируется как 0
, а затем увеличивается каждый раз, когда вы повторяете for
l oop. for
l oop выходит, когда i
не меньше array.length
(что составляет 3
), поэтому, когда for
l oop выходит, i==3
.
Следовательно, при нажатии одной из кнопок выполняется код
System.out.println(array[i].getText());
. Значение i
не изменилось с момента завершения for
l oop, поэтому это эквивалентно
System.out.println(array[3].getText());
, и это вызывает IndexOutOfBoundsException
, потому что значение индексируется в массив: 0
, 1
и 2
. Действительно, полное сообщение об ошибке:
Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
Вместо этого вам нужно использовать локальную переменную для индекса в l oop:
for (int i = 0; i < array.length; i++) {
array[i].setOnAction(e -> { /* ... */ });
}
Теперь проблема в том, что лямбда-выражение в обработчике событий не может получить доступ к локальной переменной i
, потому что она не final
(или «фактически окончательная»). Решение этой проблемы состоит в том, чтобы «захватить» значение i
на каждой итерации l oop в конечной переменной:
for (int i = 0; i < array.length; i++) {
final int index = i ;
array[i].setOnAction(e -> {
System.out.println(array[index].getText());
});
}
Конечно, вам фактически не нужен индекс; вам просто нужен элемент массива, чтобы вы могли записать его вместо:
for (int i = 0; i < array.length; i++) {
final RadioButton button = array[i] ;
button.setOnAction(e -> {
System.out.println(button.getText());
});
}
Этот код полностью идентичен (в том смысле, что компилятор преобразует следующее в то же самое) в:
for (RadioButton button : array) {
button.setOnAction(e -> {
System.out.println(button.getText());
});
}
, что, безусловно, является предпочтительной формой для for
l oop.
Вот полностью очищенная и рабочая версия кода:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
HBox p1 = new HBox();
RadioButton red = new RadioButton("RED");
RadioButton blue = new RadioButton("Blue");
RadioButton black = new RadioButton("Black");
ToggleGroup tg = new ToggleGroup();
RadioButton[] buttons = { red, blue, black };
tg.getToggles().setAll(buttons);
p1.getChildren().addAll(buttons);
for (RadioButton button : buttons) {
button.setOnAction(e -> {
System.out.println(button.getText());
});
}
Scene scene = new Scene(p1, 400, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}