JavaFX Beans 绑定突然停止工作 [英] JavaFX Beans Binding suddenly stops working

查看:35
本文介绍了JavaFX Beans 绑定突然停止工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 stops working. I don't receive an Exception, either.

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

I've tried several bindings, as well as high- and low-level approaches. Even the calculation itself (when overridden) just stops and isn't called anymore. I've also updated to the latest JDK (1.8.0_05) and rebuilt/restarted everything.

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

The following Minimal Working Example illustrates the problem. It should System.out.println the current width of the main window to STDOUT. After resizing the window for about 10 seconds, the output simply stops. I've also tried to bind the resulting property to a JavaFX control, in order to ensure the Property's continued usage, but that was of no avail. I believe I'm missing some very basic behaviour of the Property/Bindings here, Google doesn't seem to know that behaviour at all.

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(...) 方法退出,它就有资格进行垃圾回收.当垃圾收集器启动时,引用完全丢失并且绑定不再起作用.

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.

要直接查看,请添加行

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

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

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

显然,这不是您想要的:解决方法是在 start(...) 退出后保留对 boundNumberProperty 的引用.例如:

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

}

更新

遇到此问题的任何人可能还想查看 Tomas Mikula 的 ReactFX,它为此提供了更简洁的解决方法(以使用第三方库为代价,您需要花一些时间学习).Tomas 在 本博客后续文章.

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.

这篇关于JavaFX Beans 绑定突然停止工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆