2017-12-01 5 views
0

Ich möchte eine Gruppe von zehn verschiedenen Kreisen mit einer for-Schleife erstellen und jede von ihnen die Farbe ändern, wenn der Mauszeiger über eine von ihnen bewegt wird und sie auch ändern eine dritte Farbe mit einem Mausklick. Jedoch hat nur einer der Kreise - der letzte, der in der Schleife erstellt wird - die Farbänderungen, unabhängig davon, auf welchen Kreis geklickt oder über den man sich bewegt. Kann mir jemand erklären warum und wie kann ich das beheben? Ich wäre sehr dankbar. Hier ist mein Code:JavaFX - Event Handler auf verschiedenen Objekten, die von for loop erstellt werden

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

.....

enter image description here

+0

Ich kann nicht in Ihrem Code sehen, wo das Problem liegt. Sie sollten ein [minimales, vollständiges und überprüfbares Beispiel] (https://stackoverflow.com/help/mcve) erstellen. – Sedrick

+1

Sie haben aus irgendeinem Grund "Kreis" als Feld deklariert. Daher beziehen sich die Handler immer auf das Feld, das den letzten zugewiesenen Wert hat. Deklarieren Sie es stattdessen lokal in der Schleife. –

+0

Ich habe das nicht verstanden. – Sedrick

Antwort

0

Hier ist eine Beispielanwendung. Diese App verwendet Lambdas für die Zuhörer.

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; 
    } 
} 
0

Dies ist mein nehmen auf sie, die setOnMouseExited Kommentar-, wenn Sie es wollen wieder schwarz machen.

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); 
     } 
    } 

} 
+0

Vielen Dank für Ihre Antwort! Wenn ich die Anweisung ".... getChildren(). Execute (circle);" lokal in der Schleife, für jeden Kreis funktioniert es! Leider brauche ich immer noch eine Liste, weil die Kreise nicht in der Klasse erstellt werden, auf die von der Szene verwiesen wird. – Fernando

+0

Was meinst du genau? Warum können Sie sie nicht einfach zu einer Liste hinzufügen? – Emrage

1

circle ist ein Feld. Wenn die Ereignisbehandlungsroutinen ausgeführt werden, wird der Wert des Felds abgerufen, und in diesem Fall enthält er den zuletzt zugewiesenen Wert, d. H. Den zuletzt erstellten Kreis.

Beachten Sie, dass Sie auf final (effektiv endgültig für Java> = 8) lokale Variablen in umgebenden Bereichen von anonyme Klassen zugreifen können. Ich empfehle das Entfernen des circle Feld und erklärt circle, wo Sie den Wert zuweisen:

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 
    } 
}