JavaFX Beans 绑定(bind)突然停止工作

标签 java binding properties javafx javabeans

我使用 JavaFX NumberBindings 来计算某些值。最初一切都按预期工作。然而,在相当短的时间后,绑定(bind)就停止工作了。我也没有收到异常。

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

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

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);
}

}

最佳答案

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

要直接看到这个,添加行

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<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);
    }

}

更新

任何遇到这个问题的人可能还想看看 Tomas Mikula 的 ReactFX ,它为此提供了更简洁的解决方法(以使用第三方库为代价,您需要花一些时间学习)。 Tomas 在 this blog 中解释了这个问题以及 ReactFX 如何解决它和 subsequent post .

关于JavaFX Beans 绑定(bind)突然停止工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23785816/

相关文章:

java - 可运行函数取决于构造函数

xaml - 绑定(bind)到元素高度加上一个值

c# - 如何在 Xamarin.Forms 的 ListView 中绑定(bind)列表

ember.js - 如何访问传递给组件类内的 Ember 组件的属性?

c# - 在包装 PInvoke 东西的属性的 get 函数中放置大量代码是不好的做法吗?

java - CertPathValidatorException Java 尝试使用 SSL 连接到服务器数据库

java - 有什么方法可以将xml转换为java中的对象吗?

objective-c - 绑定(bind)和目标/操作?

javascript - 使用 ECMAScript 5 获取/设置属性并揭示模块模式

java - 将行号添加到已编译的类