JavaFX Beans Binding suddenly stops working

后端 未结 1 2062
生来不讨喜
生来不讨喜 2020-11-28 14:30

I use JavaFX NumberBindings in order to calculate certain values. Initially everything works as expected. After a rather small amount of time, however, the binding just stop

相关标签:
1条回答
  • 2020-11-28 15:12

    The binding uses a WeakListener to observe the value of currentWidthPlusTen. Since you don't keep a reference to the boundNumberProperty, it is eligible for garbage collection as soon as the start(...) method exits. When the garbage collector kicks in, the reference is lost entirely and the binding no longer works.

    To see this directly, add the line

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

    to the start(...) method. You can force the listener to "stop working" by clicking on the window.

    Obviously, that's not what you want: the fix is to retain the reference to boundNumberProperty after start(...) exits. For example:

    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

    Anyone running into this issue might also want to look at Tomas Mikula's ReactFX, which provides a cleaner workaround for this (at the expense of using a third-party library, which you would need to spend some time learning). Tomas explains this issue and how ReactFX resolves it in this blog and the subsequent post.

    0 讨论(0)
提交回复
热议问题