javafx - 将 ObservableList 绑定(bind)到其他两个 ObservableLists 的内容?

标签 javafx javafx-8

如果我有两个单独的 ObservableLists,并且都放在一个单独的 ObservableList 中用于 TableView...有没有办法在这两个 ObservableLists 和聚合的 ObservableLists 之间创建绑定(bind)?我试图搞乱并覆盖 ObjectBinding 的 calculate() 方法,但我认为这不是我想要的。关于如何解决这个问题的任何想法?

更新:继续相关切线以显示下面讨论的含义。这是我的 ObservableImmutableList 实现,它正在努力使用已检查的解决方案。

   package com.nield.utilities.fx;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;

import javafx.beans.InvalidationListener;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;

import com.google.common.collect.ImmutableList;


public final class ObservableImmutableList<T> implements ObservableList<T> {
    private volatile ImmutableList<T> backingList;
    private final CopyOnWriteArrayList<ListChangeListener<? super T>> listeners = new CopyOnWriteArrayList<>();
    private final CopyOnWriteArrayList<InvalidationListener> invalidationListeners = new CopyOnWriteArrayList<>();

    private final ObjectProperty<ObservableList<T>> property;

    private ObservableImmutableList(ImmutableList<T> immutableList) {
        this.backingList = immutableList;
        this.property = new SimpleObjectProperty<ObservableList<T>>(this);
    }

    public static <T> ObservableImmutableList<T> of(ImmutableList<T> immutableList) {
        return new ObservableImmutableList<T>(immutableList);
    }

    public void set(ImmutableList<T> immutableList) { 

        this.property.setValue(this);

        final ImmutableList<T> oldList = this.backingList;
        final ImmutableList<T> newList = immutableList;
        listeners.forEach(l -> l.onChanged(new Change<T>(this) {
            private int changeNum = 0;
            @Override
            public boolean next() {
                changeNum++;
                return changeNum <= 2 ? true : false;
            }
            @Override
            public boolean wasUpdated() {
                return true;
            }
            @Override
            public void reset() {
                // TODO Auto-generated method stub

            }
            @Override
            public int getFrom() {
                return 0;
            }
            @Override
            public int getTo() {
                return changeNum == 1 ? oldList.size() - 1 : newList.size() - 1;
            }
            @Override
            public List<T> getRemoved() {
                return changeNum == 1 ? oldList : ImmutableList.of();
            }
            @Override
            public List<T> getAddedSubList() { 
                return changeNum == 1 ? ImmutableList.of() : newList;
            }
            @Override
            protected int[] getPermutation() {
                int[] permutations = new int[changeNum == 1 ? oldList.size() : newList.size()];
                for (int i = 0; i < permutations.length; i++) { 
                    permutations[i] = i;
                }
                return permutations;
            }

        }));
        this.backingList = immutableList;

        invalidationListeners.forEach(l -> l.invalidated(this));

    }

    public ImmutableList<T> get() { 
        return backingList;
    }
    public ObjectProperty<ObservableList<T>> asProperty() { 
        return property;
    }

    @Override
    public int size() {
        return backingList.size();
    }

    @Override
    public boolean isEmpty() {
        return backingList.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return backingList.contains(o);
    }

    @Override
    public Iterator<T> iterator() {
        return backingList.iterator();
    }

    @Override
    public Object[] toArray() {
        return backingList.toArray();
    }

    @Override
    public <B> B[] toArray(B[] a) {
        return backingList.toArray(a);
    }

    @Override @Deprecated
    public boolean add(T e) {
        return backingList.add(e);
    }

    @Override @Deprecated
    public boolean remove(Object o) {
        return backingList.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return backingList.containsAll(c);
    }

    @Override @Deprecated
    public boolean addAll(Collection<? extends T> c) {
        return backingList.addAll(c);
    }

    @Override @Deprecated
    public boolean addAll(int index, Collection<? extends T> c) {
        return backingList.addAll(index, c);
    }

    @Override @Deprecated
    public boolean removeAll(Collection<?> c) {
        return backingList.removeAll(c);
    }

    @Override @Deprecated
    public boolean retainAll(Collection<?> c) {
        return backingList.retainAll(c);
    }

    @Override @Deprecated
    public void clear() {
        backingList.clear();
    }

    @Override
    public T get(int index) {
        return backingList.get(index);
    }

    @Override @Deprecated
    public T set(int index, T element) {
        return backingList.set(index, element);
    }

    @Override @Deprecated
    public void add(int index, T element) {
        backingList.add(index, element);
    }

    @Override @Deprecated
    public T remove(int index) {
        return backingList.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return backingList.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return backingList.lastIndexOf(o);
    }

    @Override
    public ListIterator<T> listIterator() {
        return backingList.listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
        return backingList.listIterator(index);
    }

    @Override
    public ImmutableList<T> subList(int fromIndex, int toIndex) {
        return backingList.subList(fromIndex, toIndex);
    }

    @Override
    public void addListener(InvalidationListener listener) {
        invalidationListeners.add(listener);
    }

    @Override
    public void removeListener(InvalidationListener listener) {
        invalidationListeners.remove(listener);
    }

    @Override
    public void addListener(ListChangeListener<? super T> listener) {
        listeners.add(listener);
    }

    @Override
    public void removeListener(ListChangeListener<? super T> listener) {
        listeners.remove(listener);
    }

    @Override @Deprecated
    public boolean addAll(T... elements) {
        return backingList.addAll(ImmutableList.copyOf(elements));
    }

    @Override @Deprecated
    public boolean setAll(T... elements) {
        return false;
    }

    @Override @Deprecated
    public boolean setAll(Collection<? extends T> col) {
        return false;
    }

    @Override @Deprecated
    public boolean removeAll(T... elements) {
        return backingList.removeAll(ImmutableList.copyOf(elements));
    }

    @Override @Deprecated
    public boolean retainAll(T... elements) {
        return false;
    }

    @Override @Deprecated
    public void remove(int from, int to) {
    }

    @Override
    public String toString() { 
        return backingList.toString();
    }

}

到目前为止,这是将两个 ObservableLists 合并在一起的静态工厂。它适用于 ObservableList 的标准实现,但不适用于我的 ObservableImmutableList 实现。
package com.nield.finance;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import com.google.common.collect.ImmutableList;
import com.nield.utilities.fx.ObservableImmutableList;

public class ObservableMerge {
    static ObservableImmutableList<String> a = ObservableImmutableList.of(ImmutableList.of("ABQ","DAL"));
    static ObservableImmutableList<String> b = ObservableImmutableList.of(ImmutableList.of("HOU","PHX"));

    static ObservableList<String> aandb = FXCollections.observableArrayList();


    static ObservableList<String> merge(ObservableList<String> into, ObservableList<String>... lists) {
        final ObservableList<String> list = into;
        for (ObservableList<String> l : lists) {
            list.addAll(l);
            l.addListener((javafx.collections.ListChangeListener.Change<? extends String> c) -> {
                while (c.next()) {
                    if (c.wasAdded()) {
                        list.addAll(c.getAddedSubList());
                    }
                    if (c.wasRemoved()) {
                        list.removeAll(c.getRemoved());
                    }
                    if (c.wasUpdated()) {
                        list.removeAll(c.getRemoved());
                        list.addAll(c.getAddedSubList());
                    }
                }
            });
        }

        return list;
    }
    public static void main(String...args) {
        merge(aandb, a, b);

        System.out.println(""+aandb);
        a.set(ImmutableList.of("LAX", "BUR"));
        System.out.println(""+aandb);

    }
}

And here is the static factory to merge two ObservableLists (it should work with the ObservableImmutableList too, but its not.


package com.nield.finance;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import com.google.common.collect.ImmutableList;
import com.nield.utilities.fx.ObservableImmutableList;

public class ObservableMerge {
    static ObservableImmutableList<String> a = ObservableImmutableList.of(ImmutableList.of("ABQ","DAL"));
    static ObservableImmutableList<String> b = ObservableImmutableList.of(ImmutableList.of("HOU","PHX"));

    static ObservableList<String> aandb = FXCollections.observableArrayList();


    static ObservableList<String> merge(ObservableList<String> into, ObservableList<String>... lists) {
        final ObservableList<String> list = into;
        for (ObservableList<String> l : lists) {
            list.addAll(l);
            l.addListener((javafx.collections.ListChangeListener.Change<? extends String> c) -> {
                while (c.next()) {
                    if (c.wasAdded()) {
                        list.addAll(c.getAddedSubList());
                    }
                    if (c.wasRemoved()) {
                        list.removeAll(c.getRemoved());
                    }
                    if (c.wasUpdated()) {
                        list.removeAll(c.getRemoved());
                        list.addAll(c.getAddedSubList());
                    }
                }
            });
        }

        return list;
    }
    public static void main(String...args) {
        merge(aandb, a, b);

        System.out.println(""+aandb);
        a.set(ImmutableList.of("LAX", "BUR"));
        System.out.println(""+aandb);

    }
}

最佳答案

这可能是一个起点:

    public class ObservableMerge {
        static ObservableList<String> a = FXCollections.observableArrayList();
        static ObservableList<String> b = FXCollections.observableArrayList();

        static ObservableList<String> aandb = FXCollections.observableArrayList();


        static ObservableList<String> merge(ObservableList<String> into, ObservableList<String>... lists) {
            final ObservableList<String> list = into;
            for (ObservableList<String> l : lists) {
                list.addAll(l);
                l.addListener((javafx.collections.ListChangeListener.Change<? extends String> c) -> {
                    while (c.next()) {
                        if (c.wasAdded()) {
                            list.addAll(c.getAddedSubList());
                        }
                        if (c.wasRemoved()) {
                            list.removeAll(c.getRemoved());
                        }
                    }
                });
            }

            return list;
        }
        public static void main(String...args) {
            merge(aandb, a, b);

            System.out.println(""+aandb);
            a.add("Hello");
            b.add("Peter");
            System.out.println(""+aandb);

        }
    }

关于javafx - 将 ObservableList 绑定(bind)到其他两个 ObservableLists 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27644878/

相关文章:

javafx-8 - ControlsFX自动完成,如何获取选定的对象?

JavaFX SpringBoot SpringJDBC SQLite CRUD 应用程序 - 配置

Node.js VS。用于简单客户端应用程序的 JavaFX(从服务器打印出消息)

javafx - javafx 2.1 中 FX.defer() 方法的等价物是什么

Java - 任务和 future - 我需要捕获异常还是可以将它们留给应用程序线程?

java - 如何重新初始化 NumberAxis 并移动到 JavaFX LineChart 中的下一个值?

java - 为什么 getMetadata() 不适用于 javafx 中的 m4a 文件?

JavaFX Canvas appendSVG 路径渲染行为

java - 如何在给定形状中旋转 LinearGradient?

javafx : label value updates cause error when massively setting values