2017-04-19 8 views
0

Ich versuche, ein Sudoku-Spiel in JavaFX zu machen. Ich habe das 9x9 Raster mit GridPane und TextField erstellt.JavaFX - Klicke innerhalb von GridPane druckt Pane anstelle von TextField

Jetzt möchte ich die Hintergrundfarbe des TextField ändern, wenn der Benutzer darauf klickt. Um zu überprüfen, ob alles in Ordnung ist, presse ich das Ziel des MouseEvent.

Mein Problem ist, dass, wenn ich in der Mitte von TextField klicke, das Zielfenster ist und wenn ich irgendwo anders klicke, ist das Ziel mein GridPane und die Hintergrundfarbe ändert sich.

Was soll ich tun? Ich kann nicht herausfinden, wie es geht!

public class SudokuGrid { 

public static final int GRID_SIZE = 9; 

private TextField[][] sudokuCells; 
private GridPane sudokuGrid; 

public SudokuGrid() { 
    sudokuCells = new TextField[GRID_SIZE][GRID_SIZE]; 
    createSudokuGrid(); 
    for (int row = 0; row < GRID_SIZE; row++) { 
     for(int col = 0; col < GRID_SIZE; col++) { 
      sudokuCells[row][col] = new TextField() { 
        @Override 
        public void replaceText(int start, int end, String text) { 
         // If the replaced text would end up being invalid, then simply 
         // ignore this call! 
         if (text.matches("[1-9]|\\s")) { 
          super.setText(text); 
         } 
        } 
       }; 
      sudokuCells[row][col].setPrefSize(60, 60); 
      sudokuCells[row][col].setStyle("-fx-background-color: yellow;"); 
      sudokuGrid.add(sudokuCells[row][col], col, row); 
      sudokuGrid.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() { 
       @Override 
       public void handle(MouseEvent e) { 
        Object source = e.getTarget(); 
        System.out.println(source); 
        if(source instanceof TextField) { 
         ((TextField) source).setStyle("-fx-background-color: green;"); 
        } 
       } 
       }); 
     } 
    } 
    sudokuGrid.setPrefSize(270, 270); // 30 * 9 
    sudokuGrid.setGridLinesVisible(true); 
} 

private void createSudokuGrid() { 
    sudokuGrid = new GridPane(); 
    for (int i = 0; i < GRID_SIZE; i++) { 
     RowConstraints rc = new RowConstraints(); 
     rc.setVgrow(Priority.ALWAYS) ; // allow row to grow 
     rc.setFillHeight(true); // ask nodes to fill height for row 
     // other settings as needed... 
     sudokuGrid.getRowConstraints().add(rc); 

     ColumnConstraints cc = new ColumnConstraints(); 
     cc.setHgrow(Priority.ALWAYS) ; // allow column to grow 
     cc.setFillWidth(true); // ask nodes to fill space for column 
     // other settings as needed... 
     sudokuGrid.getColumnConstraints().add(cc); 
    } 

} 

Antwort

1

Die source der Veranstaltung ist das Objekt, auf dem Sie das Ereignisfilter einstellen; d.h. in diesem Fall ist es sudokuGrid. So ist die Bedingung

if (source instanceof TextField) 

in Ihrem Handler wird nie wahr sein, da die einzige mögliche Quelle der sudokuGrid ist.

Wenn Sie die Hintergrundfarbe des Textfeldes ändern möchten, können Sie das Ereignisfilter in das Textfeld selbst hinzufügen:

TextField sudokuCell = sudokuCells[row][col]; 
sudokuCell.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> 
    sudokuCell.setStyle("-fx-background-color: green;")); 

Besser wäre noch zu Änderungen im Textfeld des fokussierten Eigentum zu reagieren (weil ein Maus-Listener nicht den Hintergrund ändern, wenn der Benutzer die Tabulatortaste verwendet, um verschiedene Textfelder zu navigieren):

TextField sudokuCell = sudokuCells[row][col]; 
sudokuCell.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { 
    if (isNowFocused) { 
     sudokuCell.setStyle("-fx-background-color: green;"); 
    } else { 
     sudokuCell.setStyle(""); 
    } 
}); 

Und noch besser wäre nur eine externe CSS-Datei zu verwenden, um dies zu tun:

Sudoku-grid.css:

.text-field:focused { 
    -fx-background-color: green ; 
} 

und dann die CSS-Datei mit dem Netz in Ihrem Java-Code Associate:

sudokuGrid.getStyleSheets().add("sudoku-grid.css"); 

und die Handler vollständig entfernen.

+0

Vielen Dank. Ich habe die letzte Option benutzt. Es scheint das einfachste zu sein. aber ich musste diesen Code hinzufügen 'sudokuCells [row] [col] .getStyleClass(). add (" text-field ");' damit es funktioniert. –

+0

@ValentinEmilCudelcu Es sollte ohne das funktionieren. Ein 'TextField' hat eine Stilklasse von' text-field' [standardmäßig] (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html#textfield). (Btw markieren Sie die Antwort als richtig, wenn sie die Frage beantwortet.) –

+0

Keine Ahnung, warum es ohne es nicht funktioniert, aber danke für Hilfe. –

Verwandte Themen