Javafx 8 替换文本区域中的文本并保持格式

Javafx 8 replace text in textarea and maintain formatting

我们正在尝试替换 TextArea 中拼写错误的单词,当该单词位于一行文本的末尾并且有一个回车符时 return 该过程失败,其他拼写错误的单词将按预期替换

Example Text
Well are we reddy for production the spell test is here but I fear the dictionary is the limiting factor ?

Here is the carriage return test in the lin abov

Hypenated words test slow-motion and lets not forget the date

就在拼写错误的单词 abov 之后,我们在 ArrayList 中有一个马车 return 文本看起来像这样

in, the, lin, abov

因为这个拼错的单词后面没有逗号,所以替换代码也会删除拼错的单词 Hypenated 因为替换代码将 "abov & Hypenated" 视为在同一索引处

运行 替换代码的结果

Here is the carriage return test in the lin above words test

如果这行代码strArray = line.split(" ");
更改为此 strArray = line.split("\s"); 问题消失了,但 TextArea 中的格式也消失了,所有回车 returns 都被删除,这不是预期的结果

问题是如何处理格式问题并且仍然替换拼写错误的单词?
旁注只有当拼错的单词位于句子末尾时才会发生这种情况,例如拼错的单词 "lin" 将根据需要替换
我们这个项目的代码行数过多,所以我们只发布导致不满意结果的代码
我们尝试只使用一个 String[ ] 数组,但收效甚微

@FXML
private void onReplace(){

    if(txtReplacementWord.getText().isEmpty()){
        txtMessage.setText("No Replacement Word");
        return;
    }

    cboMisspelledWord.getItems().remove(txtWordToReplace.getText());
    // Line Above Removes misspelled word from cboMisspelledWord 
    // ==========================================================
    String line = txaDiaryEntry.getText();
    strArray = line.split(" ");
    List<String> list = new ArrayList<>(Arrays.asList(strArray));
    for (int R = 0; R < list.size(); R++) {
        if(list.get(R).contains(txtWordToReplace.getText())){
            theIndex = R;
            System.out.println("## dex "+theIndex);//For testing
        }
    }
    System.out.println("list "+list);//For testing

    list.remove(theIndex);
    list.add(theIndex,txtReplacementWord.getText());

    sb = new StringBuilder(); 
for (String addWord : list) {
    sb.append(addWord);
    sb.append(" ");
}

    txaDiaryEntry.setText(sb.toString()); 
    txtMessage.setText("");
    txtReplacementWord.setText("");
    txtWordToReplace.setText("");
    cboCorrectSpelling.getItems().clear(); 
    cboMisspelledWord.requestFocus();

    // Code above replaces misspelled word with correct spelling in TextArea
    // =====================================================================
if(cboMisspelledWord.getItems().isEmpty()){
    onCheckSpelling();
} 
}

不要使用 split。这样你就失去了关于单词之间内容的信息。而是创建一个 Pattern 匹配词,并确保在匹配之间也复制子字符串。这样你就不会丢失任何信息。

为简单起见,以下示例通过简单地在 Map 中查找替换来替换替换逻辑,但它应该足以演示该方法:

public void start(Stage primaryStage) throws Exception {
    TextArea textArea = new TextArea(
            "Well are we reddy for production the spell test is here but I fear the dictionary is the limiting factor ?\n"
                    + "\n" + "Here is the carriage return test in the lin abov\n" + "\n"
                    + "Hypenated words test slow-motion and lets not forget the date");

    Map<String, String> replacements = new HashMap<>();
    replacements.put("lin", "line");
    replacements.put("abov", "above");

    Pattern pattern = Pattern.compile("\S+"); // pattern matching words (=non-whitespace sequences in this case)
    Button button = new Button("Replace");
    button.setOnAction(evt -> {
        String text = textArea.getText();
        StringBuilder sb = new StringBuilder();
        Matcher matcher = pattern.matcher(text);
        int lastEnd = 0;
        while (matcher.find()) {
            int startIndex = matcher.start();
            if (startIndex > lastEnd) {
                // add missing whitespace chars
                sb.append(text.substring(lastEnd, startIndex));
            }

            // replace text, if necessary
            String group = matcher.group();
            String result = replacements.get(group);
            sb.append(result == null ? group : result);

            lastEnd = matcher.end();
        }
        sb.append(text.substring(lastEnd));
        textArea.setText(sb.toString());
    });

    final Scene scene = new Scene(new VBox(textArea, button));

    primaryStage.setScene(scene);
    primaryStage.show();
}