Javafx NodeOrientation 无法按预期工作

问题描述 投票:0回答:1

我正在为阿拉伯用户开发一个应用程序,所以我已经设置:

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);
    }
}
java javafx
1个回答
0
投票

我愚蠢地认为

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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.