JavaFX Beans Binding突然停止工作

时间:2014-05-21 14:14:04

标签: java binding properties javafx javabeans

我使用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<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);
}

}

1 个答案:

答案 0 :(得分:18)

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

要直接看到这一点,请添加

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

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

显然,这不是您想要的:修复是在boundNumberProperty退出后保留对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);
    }

}

<强>更新

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