JavaFX-获取在TextArea中键入的当前单词 [英] JavaFX - get current word being typed in TextArea
问题描述
我试图获取当前在JavaFX TextArea中键入的当前单词或部分单词,以传递给一个非常基本的AutoComplete getPredictions(String prefix);方法.
I'm trying to get the current word or partial word currently being typed in a JavaFX TextArea to pass to to a very basic AutoComplete getPredictions(String prefix); method.
现在,我在KeyTyped上使用事件处理程序,我将跟踪键入的每个字符并将其与先前键入的单词连接起来,在空格上重置.在键入单词的过程中打开自动完成功能会遇到很多陷阱,如果按下退格键,并且插入符号再次位于单词的末尾,则会获得前一个单词.
Right now I am using an Event Handler on KeyTyped and I'm going to track each character typed and concatenate it with the previously typed word, resetting on a space. This is going to have a lot of pitfalls I can see with AutoComplete being turned on in the middle of typing a word, getting the previous word if backspace is hit and the caret is at the end of the word again.
我很好奇,看看是否还有其他方法可以使人想到使用TextInputControl方法将字的字符串从插入位置返回到最后一个空格的位置.我还没有按我的方式进行操作,但是我现在将发布我的内容.
I'm curious to see if there's an alternative approach anyone can think of where I simply get the String for the word from the caret position back to the last space using TextInputControl methods. I haven't got it working my way yet but I'll post what I have at this point.
我基本上需要获取当前输入的单词,并将当前插入符号的位置保留为使用类型.
I basically need to get the current word being typed preserving the current caret position as the use types.
public AutoSpellingTextArea() {
// register and handle KEY_TYPED event
this.addEventHandler(KeyEvent.KEY_TYPED,new EventHandler<KeyEvent>(){
public void handle(KeyEvent t) {
// BUG -- turning on autocomplete in middle of word.
if(autoCompleteOn) {
//TODO
String pre = getCurrentPrefix(t.getCharacter());
if(pre != null) {
List<String> choices = ac.predictCompletions(pre, NUM_COMPLETIONS);
}
}
}
});
}
private String getCurrentPrefix(String ch) {
String retVal = null;
// space entered
if(ch.equals(" ")) {
lastWord = currentPrefix;
currentPrefix = "";
return retVal;
}
// add next character to prefix string
currentPrefix = currentPrefix + ch;
return retVal;
}
推荐答案
也许您可以通过观察caratPositionProperty
并回溯到最后一个空格字符来获得所需的内容:
Maybe you can get what you need just be observing the caratPositionProperty
and backtracking to the last whitespace character:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class AutoCompleteTextAreaTest extends Application {
@Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
Label currentWord = new Label();
textArea.caretPositionProperty().addListener((obs, oldPosition, newPosition) -> {
String text = textArea.getText().substring(0, newPosition.intValue());
int index ;
for (index = text.length() - 1; index >= 0 && ! Character.isWhitespace(text.charAt(index)); index--);
String prefix = text.substring(index+1, text.length());
currentWord.setText(prefix);
});
BorderPane root = new BorderPane(textArea, currentWord, null, null, null);
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
您也可以将此想法扩展为从克拉位置开始向前搜索,这样,如果光标位于单词的中间,则可以识别出可能由于该点插入而产生的所有单词.
You could extend this idea to search forward from the carat position too, so that if the cursor is in the middle of a word, you can identify all possible words that could result from an insertion at that point.
这是一个SSCCE,使用我在网上找到的随机单词列表来证明这一点:
Here's an SSCCE demonstrating this, using a random word list I found online:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class AutoCompleteTextAreaTest extends Application {
private static final String WORD_LIST_URL = "https://raw.githubusercontent.com/dwyl/english-words/master/words.txt?raw=true";
@Override
public void start(Stage primaryStage) {
StackPane loadingRoot = new StackPane(new ProgressBar());
Scene scene = new Scene(loadingRoot, 600, 600);
List<String> words = new ArrayList<>();
Task<List<String>> loadWordsTask = new Task<List<String>>() {
@Override
public List<String> call() throws Exception {
try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL(WORD_LIST_URL)
.openConnection()
.getInputStream()))) {
return in.lines()
.collect(Collectors.toList());
}
}
};
ListView<String> suggestions = new ListView<>();
TextArea textArea = new TextArea();
textArea.caretPositionProperty().addListener((obs, oldPosition, newPosition) -> {
String text = textArea.getText().substring(0, newPosition.intValue());
int index ;
for (index = text.length() - 1;
index >= 0 && ! Character.isWhitespace(text.charAt(index));
index--);
String prefix = text.substring(index+1, text.length());
for (index = newPosition.intValue();
index < textArea.getLength() && ! Character.isWhitespace(textArea.getText().charAt(index));
index++);
String suffix = textArea.getText().substring(newPosition.intValue(), index);
// replace regex wildcards (literal ".") with "\.". Looks weird but correct...
prefix = prefix.replaceAll("\\.", "\\.");
suffix = suffix.replaceAll("\\.", "\\.");
Pattern pattern = Pattern.compile(prefix+".*"+suffix,
Pattern.CASE_INSENSITIVE);
suggestions.getItems().setAll(
words.stream().filter(word -> pattern.matcher(word).matches())
.sorted(Comparator.comparing(String::length))
.limit(100)
.collect(Collectors.toList())
);
});
BorderPane root = new BorderPane(textArea, null, suggestions, null, null);
loadWordsTask.setOnSucceeded(e -> {
words.addAll(loadWordsTask.getValue());
scene.setRoot(root);
});
loadWordsTask.setOnFailed(e -> {
suggestions.setPlaceholder(new Label("Could not load word list"));
loadWordsTask.getException().printStackTrace();
scene.setRoot(root);
});
Thread t = new Thread(loadWordsTask);
t.setDaemon(true);
t.start();
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这篇关于JavaFX-获取在TextArea中键入的当前单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!