问题
We are trying to replace misspelled words in the TextArea and when the word is at the end of a line of text and has a carriage return the process is failing other misspelled words are replace as expected
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
Just after the misspelled word abov we have a carriage return in the ArrayList the text looks like this
in, the, lin, abov
Because this misspelled word has no comma after it the replacement code also takes out the misspelled word Hypenated because the replacement code sees "abov & Hypenated" as being at the same Index
Result of running the replacement code
Here is the carriage return test in the lin above words test
If this line of code strArray = line.split(" ");
is changed to this strArray = line.split("\\s"); the issue goes away but so does the formatting in the TextArea all the carriage returns are deleted which is not a desired outcome
The question is how to deal with the formatting issue and still replace the misspelled words?
Side note this only happens when the misspelled word is at the end of a sentences for example the misspelled word "lin" will be replaced as desired
We have an excessive number of lines of code for this project so we are only posting the code that is causing the unsatisfactory results
We tried using just a String[ ] array with little or no success
@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();
}
}
回答1:
Don't use split. This way you loose the info about the content between the words. Instead create a Pattern matching words and make sure to also copy the substrings between matches. This way you don't loose any info there.
The following example replaces the replacement logic with simply looking for replacements in a Map for simplicity, but it should be sufficient to demonstrate the approach:
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();
}
来源:https://stackoverflow.com/questions/59076572/javafx-8-replace-text-in-textarea-and-maintain-formatting