JavaFX 中是否可以在创建绑定后修改绑定的依赖关系?

Cir*_*irF 4 java javafx properties

我的问题是在使用 JavaFX 实现某种图形可视化时出现的。有 2 个类,称为VertexEdge,每条边连接 2 个(可能相同)顶点。每个具有自循环的顶点(具有相同开始和结束顶点的边)都存储 αDoubleProperty作为其自循环的首选角度。该角度是根据该顶点及其所有邻居的位置计算的。但是,由于图是动态构建的,顶点的邻居可能会发生变化,从而导致依赖项的动态列表,因此我必须修改DoubleBinding角度所绑定的依赖项。

然而,created bygetDependencies中的方法只返回一个不可变的副本:DoubleBindingBindings.createDoubleBinding

@Override
public ObservableList<?> getDependencies() {
    return  ((dependencies == null) || (dependencies.length == 0))?
                FXCollections.emptyObservableList()
            : (dependencies.length == 1)?
                FXCollections.singletonObservableList(dependencies[0])
            : new ImmutableObservableList<Observable>(dependencies);
}
Run Code Online (Sandbox Code Playgroud)

尽管该类DoubleBinding有一个bind似乎满足我的需要的方法,但它是受保护的:

protected final void bind(Observable... dependencies) {
    if ((dependencies != null) && (dependencies.length > 0)) {
        if (observer == null) {
            observer = new BindingHelperObserver(this);
        }
        for (final Observable dep : dependencies) {
            dep.addListener(observer);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么有什么方法可以让我随时修改依赖项而无需定义自己的依赖项DoubleBinding,或者我可以在不触及依赖项的情况下解决我的问题吗?

Jam*_*s_D 5

您可以将您的节点绑定DoublePropertyObservableList包含邻居节点的节点。这样,如果向列表添加或从列表中删除任何内容,绑定将失效。这是这个想法的一个非常快速的演示:

import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class BindingDemo {

    public static void main(String[] args) {
        ObservableList<GraphNode> neighbors = FXCollections.observableArrayList();
        IntegerProperty total = new SimpleIntegerProperty();
        total.bind(Bindings.createIntegerBinding(
                () -> sum(neighbors),
                neighbors
        ));
        total.addListener((obs, oldTotal, newTotal) -> 
                System.out.println("Total = "+newTotal));
        for (int i = 1 ; i <= 5 ; i++) {
            System.out.println("Adding node with value "+i+":");
            neighbors.add(new GraphNode(i));
        }
    }

    private static int sum(ObservableList<GraphNode> nodes) {
        int total = 0 ;
        for (GraphNode node : nodes) {
            total += node.value();
        }
        return total ;
    }

    public static record GraphNode(int value){}
}
Run Code Online (Sandbox Code Playgroud)

输出:

Adding node with value 1:
Total = 1
Adding node with value 2:
Total = 3
Adding node with value 3:
Total = 6
Adding node with value 4:
Total = 10
Adding node with value 5:
Total = 15
Run Code Online (Sandbox Code Playgroud)

从技术上讲,这并不能真正避免“无需定义我自己的绑定”的要求,但Bindings.createXXXBinding(...)API使这样做变得非常干净。