the following exception message appears when I iterate using NORMAL for-loop that includes mouseEvent action through radioButtons.
Message: Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException
But when I iterate using for-each loop, there is no problem!
please help me, thank you
Concerned code part:
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());
});
}
I'm guessing, because your question is incomplete, that you made the loop index i
an instance variable, for some reason. I.e. you have something like:
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);
}
}
Here i
is a property of the Demo
instance (i.e. the application instance on which start()
is invoked). In the start()
method, i
is initialized to 0
and then incremented each time you iterate the for
loop. The for
loop exits when i
is no longer less than array.length
(which is 3
), so when the for
loop exits, i==3
.
Consequently, when you press one of the buttons, the code
System.out.println(array[i].getText());
is executed. The value of i
hasn't changed since the completion of the for
loop, so this is equivalent to
System.out.println(array[3].getText());
and this throws an IndexOutOfBoundsException
, because the value indexes in the array are 0
, 1
, and 2
. Indeed, the complete error message is
Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
Instead, you need to use a local variable for the index in the loop:
for (int i = 0; i < array.length; i++) {
array[i].setOnAction(e -> { /* ... */ });
}
The problem now is that the lambda expression in the event handler cannot access the local variable i
because it is not final
(or "effectively final"). The solution to this is to "capture" the value of i
on each iteration of the loop in a final variable:
for (int i = 0; i < array.length; i++) {
final int index = i ;
array[i].setOnAction(e -> {
System.out.println(array[index].getText());
});
}
Of course, you don't actually need the index; you just need the element of the array, so you could capture that instead:
for (int i = 0; i < array.length; i++) {
final RadioButton button = array[i] ;
button.setOnAction(e -> {
System.out.println(button.getText());
});
}
This code is completely identical (in the sense that the compiler converts the following to the same thing) to:
for (RadioButton button : array) {
button.setOnAction(e -> {
System.out.println(button.getText());
});
}
which is by far the preferred form for a for
loop.
Here's a fully-cleaned and working version of the code:
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);
}
}