如何在TextField中更正希腊带有重音符号的字符

JKo*_*dis 12 java javafx

我面临的问题是当我有输入(TextField,TextArea等)时,我试图插入一些包含重音符号的希腊语单词。像“ ????”(猫)这样的词可以正常工作。不幸的是,我无法键入 “ ?????”(塔希提岛)之类的词。如果我尝试复制并粘贴它或对其进行硬编码,则可以正常工作,但是当我尝试使用以下命令的组合来写单词时

Shift +';' +?

哪个应该产生“?”,而不是我得到“?”

这是一个例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Example extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {

        VBox mainBox = new VBox(10);
        mainBox.setPadding(new Insets(20));
        mainBox.setAlignment(Pos.CENTER);

        // ????? = Tahiti
        TextField field1 = new TextField("?????");
        TextField field2 = new TextField();

        mainBox.getChildren().add(field1);
        mainBox.getChildren().add(field2);

        field1.setStyle("-fx-font-size:24px");
        field2.setStyle("-fx-font-size:24px");

        stage.setScene(new Scene(mainBox));
        stage.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

下图显示了我自己输入单词时的结果

在此处输入图片说明

已安装的JRE:jre1.8.0_221

安装的JDK:jdk1.8.0_221

为了排除IDE(Eclipse)导致问题的发生,我仅使用AnchorPane和TextField在SceneBuilder上测试了此行为,并且在那里也遇到了同样的问题。但是为了争辩,我在Eclipse中拥有编辑器和所有设置来使用编码UTF-8。

因此,我想问:这是当前JRE / JDK的错误吗?如果是,是否存在我可以使用的知名解决方案,或者我应该只使用侦听器来捕获输入并自行更正?

编辑:正如塞德里克指出的那样,我可以使用alt + 0 2 3 9的组合,但这将产生另一种与希腊字母相似但不相同的字母。看下面的图片。不幸的是,这不是我的客户想要的行为,因为正确的输入方式是(使用希腊语键盘):Shift +';' +?,在哪里?是英文字母“ i”。

在此处输入图片说明

编辑2:同样,我可以使用下面的代码来破解它,但是如果我决定这样做,则必须对我的所有TextField都这样做,这是我想避免的事情。否则,我应该创建一个“虚拟” CustomTextField类,该类将扩展TextField并在那里实现修改,然后可以用CustomTextField替换项目中的所有TextField引用。

field2.setTextFormatter(new TextFormatter<>(c -> {
    String text = c.getControlNewText();

    if (text.contains("¨?") || text.contains("¨?")) { 

        // In order to "catch" a word with multiple wrong characters
        // for example if someone tries to copy/paste, I will use
        // the replaceAll() method
        text = text.replaceAll("¨?", "?");
        text = text.replaceAll("¨?", "?"); 

        // update the field 
        field2.setText(text);

        // correct the caret and anchor positions
        c.setCaretPosition(c.getCaretPosition() - 1);
        c.setAnchor(c.getCaretPosition());

        c.setText(""); // consume change because we already update it
    }
    return c;
}));
Run Code Online (Sandbox Code Playgroud)

Les*_*sum 1

我可以重现该行为。如果您在舞台上添加一个,EventHandler您可以清楚地看到问题。

\n\n
stage.addEventFilter(KeyEvent.KEY_TYPED, ev -> {\n    System.out.println("Key typed: " + ev.getCharacter());\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
Key typed: \xc2\xa8\nKey typed: \xce\x99\nKey typed: \xc2\xa8\nKey typed: \xce\xb9\n
Run Code Online (Sandbox Code Playgroud)\n\n

有一个已解决的票证描述了此问题。如果是Glass Windowing Toolkit问题,我们对此无能为力,只能提交错误报告。

\n\n

我不知道您是否可以在KeyEvents发送这些键之前捕获键入的键,但您可以在阶段级别过滤它们。

\n\n
stage.addEventFilter(KeyEvent.KEY_TYPED, new KeyTypedListener());\n
Run Code Online (Sandbox Code Playgroud)\n\n

这不是很好,而是一种更“全球”的改变行为的方式。

\n\n
public class KeyTypedListener implements EventHandler<KeyEvent> {\n\n    private boolean disabled = false;\n    private Map<String, String> charCombinations = new HashMap<>();\n    private KeyEvent pendingEvent;\n\n    public KeyTypedListener() {\n        charCombinations.put("\xc2\xa8\xce\xb9", "\xcf\x8a");\n        charCombinations.put("\xc2\xa8\xce\x99", "\xce\xaa");\n    }\n\n    @Override\n    public void handle(final KeyEvent event) {\n\n        if (disabled || event.getCharacter() == null\n                || event.getCharacter().length() != 1) {\n            return;\n        }\n\n        final String typed = event.getCharacter();\n\n        if (pendingEvent == null && isCombiCharacter(typed)) {\n            pendingEvent = event.copyFor(event.getSource(), event.getTarget());\n            event.consume();\n\n        } else if (pendingEvent != null) {\n            String combination =\n                    charCombinations.get(pendingEvent.getCharacter() + typed);\n\n            if (combination == null) {\n                disabled = true;\n                fireEvent(pendingEvent);\n                disabled = false;\n                pendingEvent = null;\n            } else {\n                event.consume();\n                pendingEvent = null;\n\n                Platform.runLater(() -> {\n                    fireEventWithCharacter(event, combination);\n                });\n            }\n        }\n    }\n\n    private boolean isCombiCharacter(final String character) {\n        return "\xc2\xa8".equals(character);\n    }\n\n    private void fireEvent(final KeyEvent event) {\n        Event.fireEvent(event.getTarget(), event);\n    }\n\n    private void fireEventWithCharacter(final KeyEvent event,\n            final String character) {\n        fireEvent(new KeyEvent(event.getSource(), event.getTarget(),\n                event.getEventType(), character, "", KeyCode.UNDEFINED,\n                event.isShiftDown(), event.isControlDown(), event.isAltDown(),\n                event.isMetaDown()));\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然你也可以创建一个新的EventDispatcher.

\n