JavaFX NodeOrientation异常:混合文本光标导航故障排查与解决
JavaFX 阿拉伯语应用光标导航异常问题及解决尝试
我正在为阿拉伯语用户开发JavaFX应用,因此设置了:
root.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
当文本框内为阿拉伯语等从右到左文本时,该设置运行正常,但当文本框包含数字或拉丁文本时,光标通过左右箭头移动的逻辑出现异常。以下是演示代码:
import javafx.application.Application; import javafx.geometry.NodeOrientation; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class NodeOrientationDemo extends Application { @Override public void start(Stage primaryStage) { TextField numbersTextField = new TextField("0123456789"); numbersTextField.setMaxSize(80, 30); TextField latinTextField = new TextField("Hello"); latinTextField.setMaxSize(80, 30); TextField arabicTextField = new TextField("مرحبا"); arabicTextField.setMaxSize(80, 30); VBox root = new VBox(10, numbersTextField, latinTextField, arabicTextField); root.setAlignment(Pos.CENTER); root.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.setTitle("NodeOrientation"); primaryStage.show(); } }
请问这是已知Bug吗?该如何解决?感谢您的帮助!
更新1:
我为所有文本框添加了事件过滤器,运行情况有所改善,但阿拉伯语文本的导航仍为反向(左箭头应等同于右箭头,右箭头应等同于左箭头)。我的计划是检测是否为阿拉伯语文本,并据此调整光标位置。
import javafx.application.Application; import javafx.geometry.NodeOrientation; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class NodeOrientationDemo extends Application { @Override public void start(Stage primaryStage) { TextField numbersTextField = new TextField("0123456789"); numbersTextField.setMaxSize(80, 30); keyboardNavigation(numbersTextField); TextField latinTextField = new TextField("Hello"); latinTextField.setMaxSize(80, 30); keyboardNavigation(latinTextField); TextField arabicTextField = new TextField("مرحبا"); arabicTextField.setMaxSize(80, 30); keyboardNavigation(arabicTextField); VBox root = new VBox(10, numbersTextField, latinTextField, arabicTextField); root.setAlignment(Pos.CENTER); root.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.setTitle("NodeOrientation"); primaryStage.show(); } private void keyboardNavigation(TextField textField) { textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.LEFT) { textField.positionCaret(textField.getCaretPosition() - 1); event.consume(); } else if (event.getCode() == KeyCode.RIGHT) { textField.positionCaret(textField.getCaretPosition() + 1); event.consume(); } }); } }
更新2:
我已实现更新1中的方案,效果良好,但仍存在一个问题:当文本框同时包含阿拉伯语文本和拉丁文本/数字时,光标导航行为不够清晰。
import javafx.application.Application; import javafx.geometry.NodeOrientation; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class NodeOrientationDemo extends Application { @Override public void start(Stage primaryStage) { TextField numbersTextField = new TextField("0123456789"); numbersTextField.setMaxSize(80, 30); keyboardNavigation(numbersTextField); TextField latinTextField = new TextField("Hello"); latinTextField.setMaxSize(80, 30); keyboardNavigation(latinTextField); TextField arabicTextField = new TextField("مرحبا"); arabicTextField.setMaxSize(80, 30); keyboardNavigation(arabicTextField); VBox root = new VBox(10, numbersTextField, latinTextField, arabicTextField); root.setAlignment(Pos.CENTER); root.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.setTitle("NodeOrientation"); primaryStage.show(); } private void keyboardNavigation(TextField textField) { textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { final int pos = clamp(1, textField.getCaretPosition(), textField.getLength()); final boolean isArabic = isArabicCharacter(textField.getText().charAt(pos - 1)); if (event.getCode() == KeyCode.LEFT) { textField.positionCaret(textField.getCaretPosition() + (isArabic ? 1 : -1)); event.consume(); } else if (event.getCode() == KeyCode.RIGHT) { textField.positionCaret(textField.getCaretPosition() + (isArabic ? -1 : 1)); event.consume(); } }); } public static boolean isArabicCharacter(char c) { return Character.UnicodeBlock.of(c) == Character.UnicodeBlock.ARABIC; } public static int clamp(int min, int value, int max) { return value < min ? min : Math.min(value, max); } }
内容的提问来源于stack exchange,提问作者Al-Anazi
相关产品推荐
相关产品推荐

