JavaFX - обработчики событий для различных объектов, созданных циклом for
Я хочу создать набор из десяти различных кругов с циклом for, чтобы каждый из них менял цвет при наведении курсора мыши на один из них, а также менял их на третий цвет щелчком мыши. Однако только один из кругов - последний из созданных в цикле - имеет изменения цвета, независимо от того, на какой круг щелкнули или навели курсор. Может кто-нибудь объяснить мне, почему и как я могу это исправить? Я был бы очень признателен. Hier это мой код:
public class View extends Parent{
BorderPane gameScreen;
Group hexaBlock;
ArrayList<Circle> circleList = new ArrayList<>();
Circle circle;
...
public View(){
gameScreen = new BorderPane();
hexaBlock = new Group();
...
for(int y=0; y<2; y++ ){
for(double x=0; x<5; x++){
circle = new Circle(xPosition(hexagon width*x), yPosition(hexagon height*4*y), radius);
circleList.add(circle);
circle.setFill(Color.BLACK);
circle.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
circle.setFill(Color.CYAN);
}
});
circle.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent t) {
circle.setFill(Color.RED);
}
});
circle.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent t) {
circle.setFill(Color.BLACK);
}
});
}
this.getChildren().add(gameScreen);
...
gameScreen.setCenter(hexaBlock);
...
hexaBlock.getChildren().addAll(circleList);
.....
3 ответа
circle
это поле. Когда выполняются обработчики событий, извлекается значение поля, и в этом случае оно содержит значение, присвоенное ему последним, то есть круг, созданный последним.
Обратите внимание, что вы можете получить доступ final
(эффективно final для java >= 8) локальные переменные в окружающих областях из классов anonymus. Я рекомендую удалить circle
поле и декларирование circle
где вы присваиваете ему значение:
for(int y=0; y<2; y++ ){
for(double x=0; x<5; x++){
final Circle circle = new Circle(xPosition(hexagon width*x), yPosition(hexagon height*4*y), radius);
...
// init circle handlers/properties
}
}
Вот пример приложения. Это приложение использует лямбды для слушателей.
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
/**
*
* @author blj0011
*/
public class JavaFXApplication54 extends Application
{
@Override
public void start(Stage primaryStage)
{
Random random = new Random();
AnchorPane root = new AnchorPane();
for (int i = 0; i < 5; i++)
{
int x1 = random.nextInt(300);
System.out.println("l: " + x1);
int y1 = random.nextInt(250);
int radius = random.nextInt(10) + 3;
root.getChildren().add(getCircle(x1, y1, radius));
}
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
Circle getCircle(int x1, int y1, int radius)
{
Circle tempCircle = new Circle(x1, y1, radius);
tempCircle.setFill(Color.BLACK);
tempCircle.setOnMousePressed(me -> tempCircle.setFill(Color.CYAN));
tempCircle.setOnMouseEntered(me -> tempCircle.setFill(Color.RED));
tempCircle.setOnMouseExited(me -> tempCircle.setFill(Color.BLACK));
return tempCircle;
}
}
Это мое мнение, раскомментируйте setOnMouseExited, если хотите, чтобы он снова стал черным.
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class CircleColours extends Application {
private final Random random = new Random();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
AnchorPane pane = new AnchorPane();
Scene scene = new Scene(pane, 600, 400);
addCircles(pane, 10, 50);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addCircles(AnchorPane pane, int amount, int radius) {
for (int i = 0; i < amount; i++) {
Circle circle = new Circle(random.nextInt((int) pane.getWidth()), random.nextInt((int) pane.getHeight()), radius);
circle.setOnMouseEntered(event -> circle.setFill(Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255))));
circle.setOnMouseClicked(event -> circle.setFill(Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255))));
//circle.setOnMouseExited(event -> circle.setFill(Color.BLACK));
pane.getChildren().add(circle);
}
}
}