如果我有两个单独的ObservableLists,并且两个都放在一个ObservableList中用于TableView ...有没有办法在这两个ObservableLists和聚合的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();
}
}
到目前为止,这是将两个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);
}
}
答案 0 :(得分:5)
这可能是一个起点:
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);
}
}
答案 1 :(得分:1)
以为我会为未来的读者记录这个。 RxJavaFX使这样的推动驱动任务变得更容易。
ObservableList<String> list1 = FXCollections.observableArrayList();
ObservableList<String> list2 = FXCollections.observableArrayList();
ObservableList<String> combinedList = FXCollections.observableArrayList();
Observable.combineLatest(
JavaFxObservable.fromObservableList(list1),
JavaFxObservable.fromObservableList(list2),
(l1,l2) -> {
ArrayList<String> combined = new ArrayList<>();
combined.addAll(l1);
combined.addAll(l2);
return combined;
}).subscribe(combinedList::setAll);
//return unmodifiable version of combinedList
这是一个完整的工作示例:
ObservableList<String> list1 = FXCollections.observableArrayList();
ObservableList<String> list2 = FXCollections.observableArrayList();
ObservableList<String> combinedList = FXCollections.observableArrayList();
Observable.combineLatest(
JavaFxObservable.fromObservableList(list1),
JavaFxObservable.fromObservableList(list2),
(l1,l2) -> {
ArrayList<String> combined = new ArrayList<>();
combined.addAll(l1);
combined.addAll(l2);
return combined;
}).subscribe(combinedList::setAll);
JavaFxObservable.fromObservableList(combinedList).subscribe(System.out::println);
list1.add("Alpha");
list2.add("Beta");
list1.add("Gamma");
list1.remove("Alpha");
list2.add("Delta");
Thread.sleep(10000);
输出
[]
[Alpha]
[Alpha, Beta]
[Alpha, Gamma, Beta]
[Gamma, Beta]
[Gamma, Beta, Delta]