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

Javafx检测文本字段更改并确定插入符号位置,javafx,textfield,changelistener,Javafx,Textfield,Changelistener,我正在Javafx中实现自动完成逻辑。TextField用于用户输入,每次更新时,都会触发侦听器。然后一个下拉菜单(即列表视图)将显示匹配的结果 所以问题是,当textProperty侦听器正在运行时,如何在TextField中获得更新的插入符号位置 我目前正在使用textfield.getCaretPosition(),但它只会返回上一个位置 任何意见都将不胜感激 commandTextField.textProperty().addListener(新的ChangeListener()){

我正在Javafx中实现自动完成逻辑。
TextField
用于用户输入,每次更新时,都会触发侦听器。然后一个下拉菜单(即
列表视图
)将显示匹配的结果

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

我目前正在使用
textfield.getCaretPosition()
,但它只会返回上一个位置

任何意见都将不胜感激

commandTextField.textProperty().addListener(新的ChangeListener()){
@凌驾

公共无效已更改(ObservalEvalue将侦听器添加到caretPositionProperty

导入javafx.application.application;
导入javafx.beans.value.ChangeListener;
导入javafx.scene.scene;
导入javafx.scene.control.TextField;
导入javafx.stage.stage;
公共类textfieldcaretap扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
public void start(Stage)引发异常{
TextField TextField=新的TextField();
场景=新场景(文本字段);
舞台场景;
stage.show();
textField.caretPositionProperty().addListener((ChangeListener)(可观察、旧值、新值)->{
System.out.println(“caretPosition=“+newValue”);
});
textField.textProperty().addListener((ChangeListener)(可观察、旧值、新值)->{
System.out.println(“text=“+newValue”);
});
}
}

这不是API的预期用途,但您可以使用由
UnaryOperator
构造的
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();
}
@覆盖
public void start(Stage primaryStage)引发异常{
ListView ListView=新建ListView();
字符串[]替换={“foo”,“bar”,“42”,“zap”};
listView.getItems().setAll(替换);
TextField TextField=新的TextField();
TextFormatter formatter=新的TextFormatter((UnaryOperator)更改->{
int a=change.getAnchor();
int b=change.getCaretPosition();
字符串newText=change.getControlNewText();
字符串前缀=newText.substring(0,Math.min(a,b));
字符串后缀=newText.substring(Math.max(a,b));
listView.getItems().clear();
用于(字符串中间:替换){
添加(前缀+中间+后缀);
}
//不要更改任何有关修改的内容
回报变化;
});
setTextFormatter(格式化程序);
场景=新场景(新VBox(listView,textField));
初级阶段。场景(场景);
primaryStage.show();
}

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

hi,因为我需要更新textProperty listener中的textfield,所以我需要在那里检索插入符号位置。我已经尝试了嵌套的listener,但它没有按预期工作。Thx!请创建一个演示我遇到的问题的t将帮助其他人了解您的问题所在看起来文本字段的内部更新尚未完成-尝试使用TextFormatterAlternative我见过一些以前实现的自动完成组合框,您也可以查看类似的内容这是否回答了您的问题?非常感谢!这一方法ch完美地解决了我的问题。