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

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

问题描述

我使用的JavaFX NumberBindings以便计算特定的值。起初一切正常。的时间相当小的量之后,然而,该结合刚刚停止工作。我没有收到异常,无论是。

我试过几个绑定,以及高,低级别的方法。即使计算本身(重写时)只是停止了,不再被调用。我也更新到最新的JDK(1.8.0_05),并重建/重新启动一切。

以下最低工作实例说明了这个问题。它应该的System.out.println主窗口STDOUT的当前宽度。调整窗口大小为约10秒后,输出简单地停止。我也试着所得到的属性绑定到JavaFX的控制,以保证物业的继续使用,但无济于事。我相信我缺少属性/绑定这里一些很基本的行为,谷歌似乎并不知道这种行为的。

 进口javafx.application.Application;
进口javafx.beans.binding.NumberBinding;
进口javafx.beans.property.IntegerProperty;
进口javafx.beans.property.SimpleIntegerProperty;
进口javafx.beans.value.ChangeListener;
进口javafx.beans.value.ObservableValue;
进口javafx.scene.Scene;
进口javafx.scene.layout.StackPane;
进口javafx.stage.Stage;公共类BindingsProblem扩展应用{@覆盖
公共无效启动(阶段primaryStage){
    //初始化...
    StackPane根=新StackPane();
    一幕一幕=新场景(根,300,250);
    primaryStage.setScene(场景);
    primaryStage.show();
    //绑定 - 这里的问题occurrs!
    NumberBinding currentWidthPlusTen = primaryStage.widthProperty()增加(10)。
    IntegerProperty boundNumberProperty =新SimpleIntegerProperty();
    boundNumberProperty.bind(currentWidthPlusTen);
    boundNumberProperty.addListener(新的ChangeListener<数字与GT;(){        @覆盖
        公共无效改变(ObservableValue&LT ;?延伸数>观察到,号码的属性oldValue,编号为newValue){
            的System.out.println(newValue.toString());
        }    });
}
公共静态无效的主要(字串[] args){
    启动(参数);
}}


解决方案

绑定使用的 WeakListener 观察 currentWidthPlusTen 。既然你不保持在 boundNumberProperty ,它是符合垃圾收集尽快启动(...)方法退出。当垃圾收集踢,参考完全丢失,绑定不再工作。

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

  root.setOnMouse pressed(事件 - >的System.gc());

启动(...)方法。您可以强制监听器停止工作通过点击窗口上。

显然,这不是你想要的一切:解决方法是保留在的参考 boundNumberProperty 启动(...)退出。例如:

 进口javafx.application.Application;
进口javafx.beans.binding.NumberBinding;
进口javafx.beans.property.IntegerProperty;
进口javafx.beans.property.SimpleIntegerProperty;
进口javafx.beans.value.ChangeListener;
进口javafx.beans.value.ObservableValue;
进口javafx.scene.Scene;
进口javafx.scene.layout.StackPane;
进口javafx.stage.Stage;公共类BindingsProblem扩展应用{    IntegerProperty boundNumberProperty;    @覆盖
    公共无效启动(阶段primaryStage){
        //初始化...
        StackPane根=新StackPane();
        一幕一幕=新场景(根,300,250);
        primaryStage.setScene(场景);
        primaryStage.show();        //绑定 - 这里的问题occurrs!
        NumberBinding currentWidthPlusTen = primaryStage.widthProperty()
                。新增(10);        boundNumberProperty =新SimpleIntegerProperty();
        boundNumberProperty.bind(currentWidthPlusTen);
        boundNumberProperty.addListener(新的ChangeListener<数字与GT;(){            @覆盖
            公共无效改变(ObservableValue&LT ;?延伸数>观察到,
                    号码属性oldValue,编号为newValue){
                的System.out.println(newValue.toString());
            }        });    }    公共静态无效的主要(字串[] args){
        启动(参数);
    }}

更新

任何人都遇到这个问题,可能也想看看托马斯Mikula的 ReactFX ,该为此提供了一个解决方法清洁(使用在一个第三方库,你将需要花一些时间学习费用)。托马斯解释了这个问题,并ReactFX如何解决它的这个博客随后的后

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.

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.

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

}

解决方案

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.

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

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