Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 条件绑定不';I don’我没有按预期工作_Java_Javafx - Fatal编程技术网

Java 条件绑定不';I don’我没有按预期工作

Java 条件绑定不';I don’我没有按预期工作,java,javafx,Java,Javafx,查看布局->initpanelsizebind()。问题是执行then(),即使panelProperty.get()为null。我做错什么了吗 您可以自己尝试,下面是完整的可复制示例。(在OpenJFX 15上测试) 可复制示例- 或者看看下面: 代码: Main.java public class Main { public static void main(String[] args) { Layout layout = new Layout();

查看
布局
->
initpanelsizebind()
。问题是执行
then()
,即使
panelProperty.get()
null
。我做错什么了吗

您可以自己尝试,下面是完整的可复制示例。(在OpenJFX 15上测试)

可复制示例-

或者看看下面:

代码:

Main.java

public class Main {
 
    public static void main(String[] args) {
        Layout layout = new Layout();
        /*
        WARNING: Exception while evaluating binding
        java.lang.NullPointerException: Cannot invoke "Panel.getWidth()" because the return value of "javafx.beans.property.ObjectProperty.get()" is null
            at Layout.lambda$initPanelSizeBinding$0(Layout.java:20)
            at javafx.beans.binding.Bindings$6.computeValue(Bindings.java:358)
            at javafx.beans.binding.ObjectBinding.get(ObjectBinding.java:157)
            at javafx.beans.binding.ObjectExpression.getValue(ObjectExpression.java:49)
            at com.sun.javafx.binding.ExpressionHelper.addListener(ExpressionHelper.java:53)
            at javafx.beans.binding.ObjectBinding.addListener(ObjectBinding.java:77)
            at javafx.beans.binding.When$ObjectCondition.<init>(When.java:757)
            at javafx.beans.binding.When$ObjectConditionBuilder.otherwise(When.java:854)
            at Layout.initPanelSizeBinding(Layout.java:24)
            at Layout.<init>(Layout.java:12)
            at Main.main(Main.java:4)
         */
    }
 
}

至少从JavaFX15开始,
然后
否则
绑定都是迫切需要评估的1。我不确定他们是否应该被热切地评价,但他们确实如此。因此,尽管您可能在
panelProperty.isNotNull()
上设置条件,但使用
createObjectBinding
创建的绑定仍然会尝试计算该值。在这种情况下,最好放弃使用
绑定。当
时,只需自己在自定义绑定中实现逻辑即可:

private ObjectBinding initPanelSizeBinding(ObjectProperty panelProperty){
DoubleBinding宽度=绑定。选择Double(panelProperty,“宽度”);
DoubleBinding高度=绑定。选择Double(panelProperty,“高度”);
返回Bindings.createObjectBinding(
() -> {
Panel Panel=panelProperty.get();
if(panel==null){
返回新尺寸2D(150.0、150.0);
}
返回新的尺寸2d(width.get(),height.get());
},
panelProperty,
宽度,
高度);
}


一,。更深入地研究,条件绑定似乎确实试图变得懒惰。不幸的是,条件绑定将侦听器添加到
then
observable的行为会导致对所述observable进行验证(并因此急切地进行评估)。这是如何实现
ExpressionHelper
的结果,它调用
observable.getValue()
来验证它。我不明白为什么代码会这样做,特别是考虑到它是一个被添加的
invalizationListener
,它应该是一个懒惰的监听器。

@kleopatra刚刚创建了一个最小的可复制示例(只包含三个类,您可以将它们复制粘贴到一个空的java项目中-在openjfx15上测试)-包括在我的帖子里嗯。。。可以复制它-不知道出了什么问题。看起来不错-希望其中一位绑定专家能给出一个解释:)@kleopatra看起来是如何实现
ExpressionHelper
的结果;当添加一个导致可观察对象计算其值的
invalizationListener
时,它调用
observable.getValue()
。我不明白它为什么会这样。嗯,很有趣。。没有通过沉思思考为什么:没有初始值,如何决定一个设置是否无效?@kleopatra the observable以“无效”开头。因此,如果初始值发生变化,那么可观察对象就不会变得“更加无效”。首次需要该值的时间是首次计算该值的时间。至少,添加一个
invalizationListener
应该强制可观察对象进行验证是没有意义的。如果涉及到
ChangeListener
,事情可能会有所不同,但是
InvalizationListener
应该是懒惰的(至少我理解是这样)。很好的一点-仅仅添加一个侦听器的行为不应该改变绑定的状态。做了一个快速测试:从ExpressionHelper删除了验证。。在控件(TextInputControlTest.selectedTextChange)和图形(围绕转换)中测试失败。所以看起来内部代码依赖于(对我来说,没有文档记录,不太容易理解)实现。我想你需要接受它。
public final class Layout {
 
    public Layout() {
        panelSize.bind(initPanelSizeBinding(panel));
        // there's no need to do anything with panel, because it's an example
    }
 
    private ObjectBinding<Dimension2D> initPanelSizeBinding(ObjectProperty<Panel> panelProperty) {
        return Bindings
                .when(panelProperty.isNotNull())
                .then(Bindings.createObjectBinding(
                        () -> new Dimension2D(panelProperty.get().getWidth(), panelProperty.get().getHeight()),
                        Bindings.selectDouble(panelProperty, "width"),
                        Bindings.selectDouble(panelProperty, "height"))
                )
                .otherwise(new Dimension2D(150.0, 150.0));
    }
 
    //------Properties
 
    //panel
 
    private final ObjectProperty<Panel> panel = new SimpleObjectProperty<>
            (Layout.this, "panel", null);
 
    public ObjectProperty<Panel> panelProperty() {
        return panel;
    }
 
    public void setPanel(Panel value) {
        panel.set(value);
    }
 
    public Panel getPanel() {
        return panel.get();
    }
 
    //panelSize
 
    private final ReadOnlyObjectWrapper<Dimension2D> panelSize = new ReadOnlyObjectWrapper<>
            (Layout.this, "panelSize");
 
    public ReadOnlyObjectProperty<Dimension2D> panelSizeProperty() {
        return panelSize.getReadOnlyProperty();
    }
 
    public Dimension2D getPanelSize() {
        return panelSize.get();
    }
 
}
public final class Panel {
 
    private final VBox rootNode;
 
    public Panel() {
        rootNode = new VBox();
        width.bind(rootNode.widthProperty());
        height.bind(rootNode.heightProperty());
    }
 
    public VBox getRootNode() {
        return rootNode;
    }
 
    //------Properties
 
    //width
 
    private final ReadOnlyDoubleWrapper width = new ReadOnlyDoubleWrapper
            (Panel.this, "width");
 
    public ReadOnlyDoubleProperty widthProperty() {
        return width.getReadOnlyProperty();
    }
 
    public double getWidth() {
        return width.get();
    }
 
    //height
 
    private final ReadOnlyDoubleWrapper height = new ReadOnlyDoubleWrapper
            (Panel.this, "height");
 
    public ReadOnlyDoubleProperty heightProperty() {
        return height.getReadOnlyProperty();
    }
 
    public double getHeight() {
        return height.get();
    }
 
}