JavaFX - 在 GridPane 内部单击会打印出 Pane 而不是 TextField
JavaFX - Clicking inside GridPane prints out Pane instead of TextField
我正在尝试用 JavaFX 制作数独游戏。我使用 GridPane 和 TextField 制作了 9x9 网格。
现在我想在用户单击 TextField 时更改其背景颜色。为了检查一切是否正常,我正在打印 MouseEvent 的目标。
我的问题是,当我单击 TextField 的中心时,目标是窗格,而当我单击其他地方时,目标是我的 GridPane 并且背景颜色正在改变。
我该怎么办?我不知道该怎么做!
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);
}
}
事件的source
是您设置事件过滤器的对象;即在这种情况下它是 sudokuGrid
。所以条件
if (source instanceof TextField)
在你的处理程序中永远不会是真的,因为唯一可能的来源是 sudokuGrid
.
如果要更改文本字段的背景颜色,可以将事件过滤器添加到文本字段本身:
TextField sudokuCell = sudokuCells[row][col];
sudokuCell.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
sudokuCell.setStyle("-fx-background-color: green;"));
更好的方法是响应文本字段焦点的变化 属性(因为如果用户使用 Tab 键导航到不同的文本字段,使用鼠标侦听器不会更改背景):
TextField sudokuCell = sudokuCells[row][col];
sudokuCell.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (isNowFocused) {
sudokuCell.setStyle("-fx-background-color: green;");
} else {
sudokuCell.setStyle("");
}
});
更好的方法是使用外部 css 文件来执行此操作:
数独-grid.css:
.text-field:focused {
-fx-background-color: green ;
}
然后在您的 Java 代码中将 CSS 文件与网格相关联:
sudokuGrid.getStyleSheets().add("sudoku-grid.css");
并完全删除处理程序。
我正在尝试用 JavaFX 制作数独游戏。我使用 GridPane 和 TextField 制作了 9x9 网格。
现在我想在用户单击 TextField 时更改其背景颜色。为了检查一切是否正常,我正在打印 MouseEvent 的目标。
我的问题是,当我单击 TextField 的中心时,目标是窗格,而当我单击其他地方时,目标是我的 GridPane 并且背景颜色正在改变。
我该怎么办?我不知道该怎么做!
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);
}
}
事件的source
是您设置事件过滤器的对象;即在这种情况下它是 sudokuGrid
。所以条件
if (source instanceof TextField)
在你的处理程序中永远不会是真的,因为唯一可能的来源是 sudokuGrid
.
如果要更改文本字段的背景颜色,可以将事件过滤器添加到文本字段本身:
TextField sudokuCell = sudokuCells[row][col];
sudokuCell.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
sudokuCell.setStyle("-fx-background-color: green;"));
更好的方法是响应文本字段焦点的变化 属性(因为如果用户使用 Tab 键导航到不同的文本字段,使用鼠标侦听器不会更改背景):
TextField sudokuCell = sudokuCells[row][col];
sudokuCell.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (isNowFocused) {
sudokuCell.setStyle("-fx-background-color: green;");
} else {
sudokuCell.setStyle("");
}
});
更好的方法是使用外部 css 文件来执行此操作:
数独-grid.css:
.text-field:focused {
-fx-background-color: green ;
}
然后在您的 Java 代码中将 CSS 文件与网格相关联:
sudokuGrid.getStyleSheets().add("sudoku-grid.css");
并完全删除处理程序。