JavaFX Beans Binding突然停止工作

我使用JavaFX NumberBindings来计算某些值。 最初一切都按预期工作。 但是,经过相当短的时间后,绑定才会停止工作。 我也没有收到例外。

我尝试了几种绑定,以及高级和低级方法。 甚至计算本身(当被覆盖时)也会停止并且不再被调用。 我还更新了最新的JDK(1.8.0_05)并重建/重新启动了所有内容。

以下最小工作示例说明了该问题。 它应该将System.out.println当前主窗口的宽度改为STDOUT。 调整窗口大小约10秒后,输出就会停止。 我还试图将结果属性绑定到JavaFX控件,以确保Property继续使用,但这无济于事。 我相信我在这里遗漏了一些非常基本的Property / Bindings行为,谷歌似乎根本不知道这种行为。

import javafx.application.Application; import javafx.beans.binding.NumberBinding; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class BindingsProblem extends Application { @Override public void start(Stage primaryStage) { // Initialization... StackPane root = new StackPane(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); // Binding - The problem occurrs here! NumberBinding currentWidthPlusTen = primaryStage.widthProperty().add(10); IntegerProperty boundNumberProperty = new SimpleIntegerProperty(); boundNumberProperty.bind(currentWidthPlusTen); boundNumberProperty.addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Number oldValue, Number newValue) { System.out.println(newValue.toString()); } }); } public static void main(String[] args) { launch(args); } } 

绑定使用WeakListener来观察currentWidthPlusTen的值。 由于您没有保留对boundNumberProperty的引用,因此只要start(...)方法退出,它就有资格进行垃圾回收。 当垃圾收集器启动时,引用完全丢失,绑定不再起作用。

要直接查看此内容,请添加该行

 root.setOnMousePressed( event -> System.gc()); 

start(...)方法。 您可以通过单击窗口强制侦听器“停止工作”。

显然,这不是你想要的:修复是在start(...)退出后保留对boundNumberProperty的引用。 例如:

 import javafx.application.Application; import javafx.beans.binding.NumberBinding; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class BindingsProblem extends Application { IntegerProperty boundNumberProperty; @Override public void start(Stage primaryStage) { // Initialization... StackPane root = new StackPane(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); // Binding - The problem occurrs here! NumberBinding currentWidthPlusTen = primaryStage.widthProperty() .add(10); boundNumberProperty = new SimpleIntegerProperty(); boundNumberProperty.bind(currentWidthPlusTen); boundNumberProperty.addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Number oldValue, Number newValue) { System.out.println(newValue.toString()); } }); } public static void main(String[] args) { launch(args); } } 

更新

遇到这个问题的任何人也可能想看看Tomas Mikula的ReactFX ,它为此提供了一个更清晰的解决方法(以牺牲使用第三方库为代价,你需要花一些时间学习)。 Tomas解释了这个问题以及ReactFX如何在此博客和后续post中解决它。