我使用 JavaFX NumberBindings 来计算某些值。最初一切都按预期进行。然而,在相当短的时间之后,绑定就停止工作。我也没有收到异常。
我尝试了几种绑定以及高级和低级方法。甚至计算本身(当被覆盖时)也会停止并且不再被调用。我还更新到了最新的 JDK (1.8.0_05) 并重建/重新启动了所有内容。
以下最小工作示例说明了该问题。它应该将System.out.println主窗口的当前宽度发送到STDOUT。调整窗口大小大约 10 秒后,输出就会停止。我还尝试将生成的属性绑定到 JavaFX 控件,以确保该属性的持续使用,但这无济于事。我相信我在这里错过了属性/绑定的一些非常基本的行为,谷歌似乎根本不知道这种行为。
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);
}
}
绑定使用弱监听器 http://docs.oracle.com/javase/8/javafx/api/javafx/beans/value/WeakChangeListener.html观察值currentWidthPlusTen
。由于您没有保留对boundNumberProperty
,一旦满足,它就有资格进行垃圾收集start(...)
方法退出。当垃圾收集器启动时,引用将完全丢失,并且绑定不再起作用。
要直接查看此内容,请添加行
root.setOnMousePressed( event -> System.gc());
to the start(...)
方法。您可以通过单击窗口强制侦听器“停止工作”。
显然,这不是您想要的:修复方法是保留对boundNumberProperty
after start(...)
退出。例如:
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<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);
}
}
Update
遇到这个问题的任何人可能还想看看 Tomas Mikula 的ReactFX https://github.com/TomasMikula/ReactFX/releases/tag/v2.0-M2,它为此提供了一个更清晰的解决方法(以使用第三方库为代价,您需要花一些时间学习该库)。 Tomas 解释了这个问题以及 ReactFX 如何解决它这个博客 http://tomasmikula.github.io/blog/2015/02/10/the-trouble-with-weak-listeners.html和后续帖子 http://tomasmikula.github.io/blog/2015/02/10/val-a-better-observablevalue.html.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)