You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:32:06