以下问题是我的JavaFX应用程序中的一个错误的来源.奇怪的是,行为取决于特定的JavaFX属性是否附加了侦听器.当属性被ChangeListener
观察时,一切都会正常工作,否则就不会.它开始把我逼疯了.
我设法将其分解为一个最小的代码示例.首先,我们需要一个公开不时更改的属性的类.在这里它被称为nameProperty()
.在本例中,我 Select 派生一个不断修改属性的单独线程,但在实际应用程序中,这是通过用户交互实现的.
class TestClass {
private final SimpleObjectProperty<String> name = new SimpleObjectProperty<>();
public TestClass() {
new Thread(() -> {
while(true) {
try {
Thread.sleep(1000);
Platform.runLater(() -> name.set("A"));
Thread.sleep(1000);
Platform.runLater(() -> name.set("B"));
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
public ReadOnlyObjectProperty<String> nameProperty() {
return name;
}
}
在Main方法中,在FX应用程序线程上,使用一个提取程序创建一个ObservableList<TestClass>
,以便由ListChangeListener
报告对列表元素的nameProperty()
的更改.然后,我们创建测试类的一个实例,将其添加到列表中,并添加ListChangeListener
以观察列表的更新.
public static void main(String[] args) throws Exception {
Platform.startup(() -> {
Callback<TestClass, Observable[]> extractor = obj -> new Observable[]{ obj.nameProperty() };
ObservableList<TestClass> list = FXCollections.observableArrayList(extractor);
TestClass test = new TestClass();
list.add(test);
list.addListener((ListChangeListener<TestClass>) c -> {
while(c.next()) {
if(c.wasUpdated()) {
System.out.println("List element was updated");
}
}
});
});
Thread.sleep(60*60*1000);
}
我对输出的预期是,由于列表提取程序和不断修改的属性,它将如下所示:
List element was updated
List element was updated
List element was updated
List element was updated
List element was updated
...
但实际上,它看起来是这样的:
List element was updated
*silence*
现在奇怪的是,只要在代码中的任何位置向nameProperty()
添加一个ChangeListener
,例如
test.nameProperty().addListener(((observable, oldValue, newValue) -> {}));
它似乎就像预期的那样工作,并且列表不断地生成更改通知.
仅仅观察一个属性不应该改变与该属性绑定的其他东西的行为,对吗?但如果这是JavaFX中的一个错误,在我看来,这将是一个非常明显和根本的错误.所以,也许我确实搞砸了什么,尽管这个程序看起来很简单.顺便说一下,我在Windows10上使用的是OpenJFX版本21.