gpt4 book ai didi

java - 使用 JavaFX 中的箭头键导航出 GridPane 中的 TextField

转载 作者:行者123 更新时间:2023-12-01 23:55:38 27 4
gpt4 key购买 nike

我正在使用 JavaFX 库在 Java 中制作一个数独解算器程序。该程序包含一个交互式数独板,该板由 GridPane 中的一系列 TextField 组成。董事会看起来像这样:

The Sodoku Board

现在,光标位于最左上角的 TextField。如果字段中有文本,用户可以使用箭头键在文本中移动光标。但是,我希望用户能够使用箭头键导航到不同的 TextField。问题是,该字段处于“键入模式”(我不知道官方术语),因此箭头键只能将光标移动到文本中的不同点,否则它会停留在同一字段中。

这就是我的意思:

enter image description here

假装我画的那条线是光标。现在,如果我单击左箭头键,光标将移动到 1 的左侧,但我希望它移动到左侧的 TextField。如果我单击向下箭头键,则没有任何反应,因为 1 下方没有可供光标导航到的文本,但我希望它移至下面的 TextField

GridPane 的代码是这样的:

TextField[][] squares = new TextField[9][9];
GridPane grid = new GridPane();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
squares[i][j] = new TextField();
squares[i][j].setPrefHeight(8);
squares[i][j].setPrefWidth(25);
grid.add(squares[i][j], j, i);
}
}
grid.setAlignment(Pos.CENTER);

squares 数组让我可以访问 GridPane 中的各个 TextField

关于如何解决这个问题有什么建议吗?

最佳答案

要完全避免焦点 TextField 处理箭头键,您需要在 KeyEvent 到达所述 TextField 之前拦截它。这可以通过向 GridPane 添加事件 filter 并适本地使用事件来实现。如果您不确定为什么会这样,您可以查看 JavaFX: Handling Events教程。

然后您可以使用 Node#requestFocus() 以编程方式更改焦点节点。

我还建议设置每个 TextFieldprefColumnCount,而不是尝试手动设置首选尺寸。这样,首选尺寸是根据字体大小计算的。

这是一个例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class App extends Application {

private TextField[][] fields;

@Override
public void start(Stage primaryStage) {
GridPane grid = new GridPane();
grid.setHgap(3);
grid.setVgap(3);
grid.setPadding(new Insets(5));
grid.setAlignment(Pos.CENTER);
grid.addEventFilter(KeyEvent.KEY_PRESSED, this::handleArrowNavigation);

fields = new TextField[9][9];

for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
fields[i][j] = createTextField();
grid.add(fields[i][j], j, i);
}
}

primaryStage.setScene(new Scene(grid));
primaryStage.show();
}

private void handleArrowNavigation(KeyEvent event) {
Node source = (Node) event.getSource(); // the GridPane
Node focused = source.getScene().getFocusOwner();
if (event.getCode().isArrowKey() && focused.getParent() == source) {
int row = GridPane.getRowIndex(focused);
int col = GridPane.getColumnIndex(focused);
// Switch expressions were standardized in Java 14
switch (event.getCode()) {
case LEFT -> fields[row][Math.max(0, col - 1)].requestFocus();
case RIGHT -> fields[row][Math.min(8, col + 1)].requestFocus();
case UP -> fields[Math.max(0, row - 1)][col].requestFocus();
case DOWN -> fields[Math.min(8, row + 1)][col].requestFocus();
}
event.consume();
}
}

private TextField createTextField() {
TextField field = new TextField();
// Rather than setting the pref sizes manually this will
// compute the pref sizes based on the font size.
field.setPrefColumnCount(1);
field.setFont(Font.font(20));
field.setTextFormatter(
new TextFormatter<>(
change -> {
// Only allow the text to be empty or a single digit between 1-9
if (change.getControlNewText().matches("[1-9]?")) {
// Without this the text goes "off screen" to the left. This also
// seems to have the added benefit of selecting the just-entered
// text, which makes replacing it a simple matter of typing another
// digit.
change.setCaretPosition(0);
return change;
}
return null;
}));
return field;
}
}

上面还向每个 TextField 添加了一个 TextFormatter 以显示一种将文本限制为 1 到 9 之间的数字的方法。注意箭头导航不会“环绕” "当它到达行或列的末尾时。如果需要,您当然可以修改代码来实现这一点。

您可能需要考虑为游戏创建模型。这样,业务逻辑就不会直接绑定(bind)到 JavaFX UI 对象。当您更新模型时,它会通知 View (可能通过“ View 模型”,具体取决于体系结构),并且 View 会相应地自行更新。

关于java - 使用 JavaFX 中的箭头键导航出 GridPane 中的 TextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62795393/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com