2

SimpleElement重みフィールドを持つクラスがあり、2 番目のクラスにはリストSimpleElementと、リストに含まれる他のすべての重みの合計に依存する重みフィールドがありSimpleElementます。バインディングによってそれを行う方法を知っている人はいますか?

私のコード:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;

public class SimpleElement {

    IntegerProperty weight;

    public SimpleElement() {
        weight = new SimpleIntegerProperty();
    }

    public int getWeight() {
        return weight.get();
    }

    public void setWeight(int weight) {
        this.weight.set(weight);
    }

    public IntegerProperty weightProperty() {
        return weight;
    }
}

import java.util.ArrayList;
import java.util.List;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;

public class RootElement {

    List<SimpleElement> elements;
    IntegerProperty weight;

    public RootElement() {
        elements = new ArrayList<>();
        weight = new SimpleIntegerProperty();
    }

    public void addelements(SimpleElement element) {
        elements.add(element);
    }
}
4

3 に答える 3

1

Crferreira の回答では、Fluent API を使用してバインディングのチェーンを構築しています。オブジェクトを削除または置換できる場合、クリーニングと保守が難しいことがわかりました。低レベル API を使用することをお勧めします。

JavaFX API には事前に作成されたバインディングの膨大なセットがありますが、ListBinding は、その要素の 1 つが新しいプロパティ値を取得しても無効になりません。したがって、リストの変更をリッスンし、新しいプロパティ自体に再バインドする IntegerBinding サブクラスを作成する必要があります。

同様の回答のコードに基づいています。

import java.util.ArrayList;
import java.util.List;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;

class RootElement {

    ObservableList<SimpleElement> elements = FXCollections.observableList(new ArrayList<SimpleElement>());

    IntegerBinding totalWeight;

    public RootElement() {

        totalWeight = new SumOfWeightsForListOfSimpleElementsIntegerBinding(elements);

    }

    public void addElement(SimpleElement element) {

        elements.add(element);

    }

    public void removeElement(SimpleElement element) {

        elements.remove(element);

    }

    public Integer getWeigth() {
        return totalWeight.getValue();
    }

}

class SimpleElement {

    IntegerProperty weight;

    public SimpleElement() {
        this(0);
    }

    public SimpleElement(Integer weight) {
        this.weight = new SimpleIntegerProperty(weight);
    }

    public int getWeight() {
        return weight.get();
    }

    public void setWeight(int weight) {
        this.weight.set(weight);
    }

    public IntegerProperty weightProperty() {
        return weight;
    }

}

class SumOfWeightsForListOfSimpleElementsIntegerBinding extends IntegerBinding {

    // Reference to our observable list 
    private final ObservableList<SimpleElement> boundList;

    // Array of currently observed properties of elements of our list
    private IntegerProperty[] observedProperties = {};

    // Listener that has to call rebinding in response of any change in observable list
    private final ListChangeListener<SimpleElement> BOUND_LIST_CHANGE_LISTENER
            = (ListChangeListener.Change<? extends SimpleElement> change) -> {
                refreshBinding();
            };

    SumOfWeightsForListOfSimpleElementsIntegerBinding(ObservableList<SimpleElement> boundList) {
        this.boundList = boundList;
        boundList.addListener(BOUND_LIST_CHANGE_LISTENER);
        refreshBinding();
    }

    @Override
    protected int computeValue() {
        int i = 0;
        for (IntegerProperty bp : observedProperties) {
            i += bp.get();
        }

        return i;
    }

    @Override
    public void dispose() {
        boundList.removeListener(BOUND_LIST_CHANGE_LISTENER);
        unbind(observedProperties);
    }

    private void refreshBinding() {
        // Clean old properties from IntegerBinding's inner listener
        unbind(observedProperties);

        // Load new properties    
        List<IntegerProperty> tmplist = new ArrayList<>();
        boundList.stream().map((boundList1) -> boundList1.weightProperty()).forEach((integerProperty) -> {
            tmplist.add(integerProperty);
        });

        observedProperties = tmplist.toArray(new IntegerProperty[0]);

        // Bind IntegerBinding's inner listener to all new properties
        super.bind(observedProperties);

        // Invalidate binding to generate events
        // Eager/Lazy recalc depends on type of listeners attached to this instance
        // see IntegerBinding sources
        this.invalidate();
    }
}

public class Main {

    public static void main(String[] args) {
        SimpleElement se1 = new SimpleElement(10);
        SimpleElement se2 = new SimpleElement(20);
        SimpleElement se3 = new SimpleElement(30);
        RootElement root = new RootElement();

        root.totalWeight.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            System.out.println(newValue);
        });

        root.addElement(se1);
        root.addElement(se2);
        root.addElement(se3);

        se1.setWeight(1000);
        root.removeElement(se3);

    }

}

リスト内の要素のプロパティの合計を監視するような一般的なタスクに、醜いボイラープレートが必要になるのは悲しいことです。

于 2014-06-18T02:11:17.717 に答える