如果我有两个单独的ObservableLists,并且都将它们放在一个TableView的单个ObservableList中,那么有没有办法在这两个ObservableLists和聚合的列表之间创建绑定?我试图弄乱并重写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();
}
}
到目前为止,这是将两个ObservableList合并在一起的静态工厂。它适用于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);
}
}