Javafx检测文本字段的更改并确定插入符号的位置



我正在Javafx中实现自动完成逻辑。TextField用于用户输入,每次更新时,侦听器都会被触发。然后作为listView的下拉菜单将显示匹配的结果。

所以问题是,当textProperty侦听器正在处理时,我如何获得TextField中更新的插入符号位置?

我目前正在使用textfield.getCaretPosition(),但它只会返回以前的位置。

如有任何意见,我们将不胜感激!

commandTextField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable,
String oldText, String newText) {
// Following line will return previous caret position
commandTextField.getCaretPosition();
...//autocomplete logic omitted
}
});

编辑:我需要获得插入符号位置的原因是我需要知道输入更改的位置,并相应地显示建议。

textField.caretPositionProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
caretPosition = newValue.intValue();
});
textField.textProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> {
...//autocomplete Logic
}

在上面的情况下,textProperty侦听器将首先被调用,然后是caretPositionProperty,因此在我的情况下无法获得更新的插入符号位置。

这不是API的预期用途,但您可以使用以UnaryOperator<TextFormatter.Change>为参数构建的TextFormatter。这通常用于防止/修改对文本的不希望的更改,但在这种情况下,我们只会使用Change对象来获得所需的数据。

下面的例子"建议"了每一个用一些字符串替换所选部分的可能性:

@Override
public void start(Stage primaryStage) throws Exception {
ListView<String> listView = new ListView<>();
String[] replacements = { "foo", "bar", "42", "zap" };
listView.getItems().setAll(replacements);
TextField textField = new TextField();
TextFormatter<?> formatter = new TextFormatter<>((UnaryOperator<TextFormatter.Change>) change -> {
int a = change.getAnchor();
int b = change.getCaretPosition();
String newText = change.getControlNewText();
String prefix = newText.substring(0, Math.min(a, b));
String suffix = newText.substring(Math.max(a, b));
listView.getItems().clear();
for (String mid : replacements) {
listView.getItems().add(prefix + mid + suffix);
}
// do not change anything about the modification
return change;
});
textField.setTextFormatter(formatter);
Scene scene = new Scene(new VBox(listView, textField));
primaryStage.setScene(scene);
primaryStage.show();
}

还有很多可用的属性,包括更改前的文本、carret和锚点位置,请参阅javadoc。

将侦听器添加到cartePositionProperty。

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class TextFieldCaretApp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {            
TextField textField = new TextField();
Scene scene = new Scene(textField);
stage.setScene(scene);
stage.show();
textField.caretPositionProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
System.out.println("caretPosition=" + newValue);
});
textField.textProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> {
System.out.println("text=" + newValue);
});
}
}

最新更新