老问题,我知道。对于任何错误的格式或缺少的代码行,我提前道歉。我是老用户,第一次投稿。
无论如何,由于从 JDK11 中删除了 JavaFX,我不得不编写自己的 ObservableList 版本。当然,我们可以将 JavaFX 与 JMods 或 Maven 一起使用,但这对于 FXCollections 来说似乎有点矫枉过正。
长话短说……呃:)
我开始阅读这个老问题,但答案并不完全适合我的需要,所以我添加了一个自定义事件/侦听器类。
想我可以分享,因为这个网站已经将我的编码提高了 10 倍。
public static void main(String[] args) {
BackedList<String> list = new BackedList();
list.addListener(new BackedListListener<String>(){
@Override
public void setOnChanged(ListChangeEvent<String> event) {
if (event.wasAdded()) {
event.getChangeList().forEach(e->{
// do whatever you need to do
System.out.println("added: " + e);
});
}
if (event.wasRemoved()) {
// do whatever you need to dl
event.getChangeList().forEach(e->{System.out.println(e + " was removed");});
}
}
});
类:BackedObservableList
public class BackedObservableList<T> implements List<T> {
private final List<T> backed;
public BackedObservableList() {
backed = new ArrayList();
}
public BackedObservableList(List<T> backed) {
this.backed = backed;
}
/*
You will want to override every method. For any method that performs an add/remove
operation, you will have to do some coding / testing. I'll do an add() op, a remove()
op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list.
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.
*/
@Override
public boolean add(T e) {
if (backed.add(e)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
notifyListeners(event);
return true;
}
return false;
}
}
@Override
public boolean remove(Object o) {
if (backed.remove(o)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o),
backed.indexOf(o) + 1, false, o);
notifyListeners(event);
return true;
}
return false;
}
/*
The iterator seemed easy enough, until I remembered the iterator.remove() call.
I still haven't fully tested it (it works, but only as far as I've used it)
*/
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
T currentItem = null;
int currentIndex = 0;
@Override
public boolean hasNext() {
return backed.size() > currentIndex;
}
@Override
public T next() {
return currentItem = backed.get(currentIndex++);
}
@Override
public void remove() {
if (backed.remove(currentItem)) {
currentIndex--;
notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
}
}
};
}
private void notifyListeners(ListChangeEvent<T> event) {
for (BackedListListener<T> listener : listeners) {
listener.setOnChanged(event);
}
}
private final List<BackedListListener> listeners = new ArrayList();
public void addListener(BackedListListener<T> listener) {
listeners.add(listener);
}
类:ListChangeEvent
它只是提供对支持列表的引用(您可能希望使用Collections.unmodifiableList()
public class ListChangeEvent<T> {
private final List<T> source;
private final List<T> changeList;
private final boolean wasAdded;
private final int to, from;
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, T... changeItems) {
this(source, from, to, wasAdded, Arrays.asList(changeItems));
}
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, List<T> changeItems) {
this.source = source;
this.changeList = changeItems;
this.wasAdded = wasAdded;
this.to = to;
this.from = from;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public List<T> getSource() {
return source;
}
public List<T> getChangeList() {
return changeList;
}
public boolean wasAdded() {
return wasAdded;
}
public boolean wasRemoved() {
return !wasAdded;
}
}
类:BackedListListener
/*
Finally a little functional interface... or, because I was too lazy to change it to one, a simple one-liner abstract class with some generics
*/
public abstract class BackedListListener<T> {
public abstract void setOnChanged(ListChangeEvent<T> event);
}