我使用
JavaFX NumberBindings来计算某些值.最初,一切都按预期工作.然而,经过相当短的时间,绑定只是停止工作.我也没有收到异常.
我尝试了几个绑定,以及高级和低级方法.即使计算本身(当被覆盖)只是停止,不再被调用.我也更新到最新的JDK(1.8.0_05)并重建/重新启动了一切.
以下最小工作示例说明了此问题. System.out.println将主窗口的当前宽度设置为STDOUT.调整窗口大约10秒后,输出就会停止.我还试图将结果属性绑定到JavaFX控件,以确保Property继续使用,但这无济于事.我相信我在这里遗漏了一些非常基本的财产/绑定行为,Google似乎并不知道这一行为.
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<Number>() {
@Override
public void changed(ObservableValue<? extends Number> 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(…)退出后保留对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,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<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable,Number newValue) {
System.out.println(newValue.toString());
}
});
}
public static void main(String[] args) {
launch(args);
}
}
更新
任何遇到这个问题的人也可能想看看Tomas Mikula的ReactFX,它为此提供了一个更清洁的解决方法(牺牲了使用第三方库,您需要花费一些时间学习). Tomas解释了这个问题,ReactFX如何在this blog和subsequent post中解决这个问题.