JavaFX TextField 对用户输入做出反应,但对 setText() 没有反应
JavaFX TextField react on userinput, but not on setText()
如何为 JavaFX 文本字段编写 ChangeListener,它只对用户输入作出反应,而不对 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
}
});
这样的问题总让我觉得你的设计有问题。文本代表一些数据;您正在注册一个侦听器,因为您对数据何时更改感兴趣 - 为什么 它更改并不重要。如果它确实重要,您可能需要一个 属性 来表示您的数据,它不同于文本字段固有的 属性。
最后一点也给出了一个可能的解决方案:
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(...)
的调用(在文本字段内部),从而调用您的侦听器。这里新的文本字段值与您自定义的 属性 值不同,因此调用了代码的主要部分。
如何为 JavaFX 文本字段编写 ChangeListener,它只对用户输入作出反应,而不对 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
}
});
这样的问题总让我觉得你的设计有问题。文本代表一些数据;您正在注册一个侦听器,因为您对数据何时更改感兴趣 - 为什么 它更改并不重要。如果它确实重要,您可能需要一个 属性 来表示您的数据,它不同于文本字段固有的 属性。
最后一点也给出了一个可能的解决方案:
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(...)
的调用(在文本字段内部),从而调用您的侦听器。这里新的文本字段值与您自定义的 属性 值不同,因此调用了代码的主要部分。