我正在为阿拉伯用户开发一个应用程序,所以我已经设置:
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();
}
}
这是一个已知的错误吗?那我该如何解决呢?
感谢任何帮助,提前致谢!
更新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:
我已经实施了
update 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);
}
}
我愚蠢地认为
update 2
(在问题中)可以解决问题,但事实并非如此。根据我的尝试,你根本无法摆脱“反转逻辑”。相反,您可以将其放在阿拉伯文本中,反之亦然。
以下代码为我完成了这项工作:
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;
import java.util.Objects;
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 -> {
boolean containsArabicText = false;
for (char c : textField.getText().toCharArray()) {
if (!isArabicCharacter(c)) continue;
containsArabicText = true;
}
final KeyCode code = event.getCode();
if (code == KeyCode.LEFT) {
textField.positionCaret(textField.getCaretPosition() + (containsArabicText ? 1 : -1));
event.consume();
} else if (code == KeyCode.RIGHT) {
textField.positionCaret(textField.getCaretPosition() + (containsArabicText ? -1 : 1));
event.consume();
}
});
}
public static boolean isArabicCharacter(char c) {
return Character.UnicodeBlock.of(c) == Character.UnicodeBlock.ARABIC;
}
}