JavaFX TextField对userinput作出反应,但不对setText()作出反应

时间:2015-02-09 22:59:41

标签: javafx

如何为JavaFX Textfield编写ChangeListener,它只对userinput做出反应,而不是对setText方法做出反应?

textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable,
            String oldValue, String newValue) {

        // code is executed, when user changes text,
        // but also, when setText(..) is called
    }
});

1 个答案:

答案 0 :(得分:2)

这样的问题总让我觉得你的设计有些不对劲。该文字代表一些数据;你正在注册一个听众,因为你对数据的变化感兴趣 - 它真的不重要为什么它发生了变化。如果它确实重要,您可能需要一个属性来表示与文本字段固有属性不同的数据。

最后一点也给出了一个可能的解决方案:

final TextField textField = new TextField(); // or injected from FXML, etc

final StringProperty text = new SimpleStringProperty(textField.getText());
text.addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
        textField.setText(newValue);
    }
});

textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
        if (! newValue.equals(text.get())) { // textField's text was changed directly (i.e. by user)
            // perform whatever action you need...

            // update the text property so the two remain equal:
            text.set(newValue);
        }
    }
});

现在重要的是,您永远不会致电textField.setText(...),而是始终致电text.set(...)。这导致通过第一个侦听器对textField.setText(...)进行编程调用。这会调用第二个侦听器,但此时文本字段的新值将与自定义属性的值相同。

另一方面,如果用户键入文本字段,则会创建一个调用(文本字段的内部)到textField.textProperty().set(...),调用您的监听器。这里新的文本字段值与您的自定义属性值不同,因此调用了代码的主要部分。