JavaFX:可观察模型/列表&;自动用户界面刷新
几天来,我一直在尝试让用户界面自动刷新工作与WPF一样,老实说,我对在谷歌上找到的解决方案非常不满意,因为它们大多是黑客/变通方法 我想要的是:JavaFX:可观察模型/列表&;自动用户界面刷新,java,javafx,observable,Java,Javafx,Observable,几天来,我一直在尝试让用户界面自动刷新工作与WPF一样,老实说,我对在谷歌上找到的解决方案非常不满意,因为它们大多是黑客/变通方法 我想要的是: 模型列表中的更改会导致UI更改 模型属性的更改会导致UI更改 模型属性的更改会传播到包含列表并导致UI更改 以下是我目前的情况: 模型类必须基于ObservaleModel 模型类支持手动触发属性更改(还没有自动触发) 模型列表支持自动触发集合更改和包含项中发生的属性更改 ListView可以直接使用ObservableModelList Tabl
- 模型列表中的更改会导致UI更改
- 模型属性的更改会导致UI更改
- 模型属性的更改会传播到包含列表并导致UI更改
import java.util.concurrent.CopyOnWriteArrayList;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
public class ObservableModel implements Observable
{
protected final CopyOnWriteArrayList<InvalidationListener> listenerList = new CopyOnWriteArrayList<>();
@Override
public void addListener(InvalidationListener listener)
{
this.listenerList.add(listener);
}
@Override
public void removeListener(InvalidationListener listener)
{
this.listenerList.remove(listener);
}
public void clearListeners()
{
this.listenerList.clear();
}
public void fireValueChangedEvent()
{
Platform.runLater(this::doFireValueChangedEvent);
}
protected void doFireValueChangedEvent()
{
this.listenerList.forEach(lsnr -> lsnr.invalidated(this));
}
}
import java.util.concurrent.CopyOnWriteArrayList;
导入javafx.application.Platform;
导入javafx.beans.InvalizationListener;
导入javafx.beans.Observable;
公共类ObservableModel实现了Observable
{
受保护的最终CopyOnWriteArrayList listenerList=新CopyOnWriteArrayList();
@凌驾
public void addListener(invalizationListener侦听器)
{
this.listenerList.add(侦听器);
}
@凌驾
公共void RemovelListener(InvalizationListener侦听器)
{
this.listenerList.remove(侦听器);
}
public void clearListeners()
{
this.listenerList.clear();
}
public void fireValueChangedEvent()
{
runLater(this::doFireValueChangedEvent);
}
受保护的无效doFireValueChangedEvent()
{
this.listenerList.forEach(lsnr->lsnr.invalidated(this));
}
}
可观察模型列表:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.ModifiableObservableListBase;
import javafx.collections.ObservableList;
public class ObservableModelList<E> extends ModifiableObservableListBase<E>
implements ObservableList<E>, RandomAccess
{
private final InvalidationListener itemListener = new InvalidationListener()
{
@Override
public void invalidated(Observable observable)
{
int index = ObservableModelList.this.indexOf(observable);
if (index >= 0)
{
ObservableModelList.this.fireChange(index);
}
}
};
private final List<E> backingList;
public ObservableModelList()
{
this(new ArrayList<E>());
}
public ObservableModelList(List<E> list)
{
this.backingList = list;
for (E e : this.backingList)
{
if (e instanceof Observable)
((Observable) e).addListener(this.itemListener);
}
}
@Override
public E get(int index)
{
return this.backingList.get(index);
}
@Override
public int size()
{
return this.backingList.size();
}
@Override
public int indexOf(Object o)
{
return this.backingList.indexOf(o);
}
@Override
public int lastIndexOf(Object o)
{
return this.backingList.lastIndexOf(o);
}
@Override
public boolean contains(Object o)
{
return this.backingList.contains(o);
}
@Override
public boolean containsAll(Collection<?> c)
{
return this.backingList.containsAll(c);
}
@Override
public void clear()
{
for (E e : this.backingList)
{
if (e instanceof Observable)
((Observable) e).removeListener(this.itemListener);
}
if (hasListeners())
{
beginChange();
nextRemove(0, this);
}
this.backingList.clear();
++this.modCount;
if (hasListeners())
{
endChange();
}
}
@Override
public void remove(int fromIndex, int toIndex)
{
beginChange();
for (int i = fromIndex; i < toIndex; ++i)
{
remove(fromIndex);
}
endChange();
}
@Override
public boolean removeAll(Collection<?> c)
{
beginChange();
boolean modified = false;
for (int i = 0; i < size(); ++i)
{
if (c.contains(get(i)))
{
remove(i);
--i;
modified = true;
}
}
endChange();
return modified;
}
@Override
public boolean retainAll(Collection<?> c)
{
beginChange();
boolean modified = false;
for (int i = 0; i < size(); ++i)
{
if (!c.contains(get(i)))
{
remove(i);
--i;
modified = true;
}
}
endChange();
return modified;
}
public void fireChange(int index)
{
this.beginChange();
this.nextUpdate(index);
this.endChange();
}
public void fireChanges(int startIndex, int endIndex)
{
this.beginChange();
for (int i = startIndex; i <= endIndex; i++)
this.nextUpdate(i);
this.endChange();
}
@Override
protected void doAdd(int index, E element)
{
if (element instanceof Observable)
((Observable) element).addListener(this.itemListener);
this.backingList.add(index, element);
}
@Override
protected E doSet(int index, E element)
{
E removed = this.backingList.set(index, element);
if (removed instanceof Observable)
((Observable) removed).removeListener(this.itemListener);
if (element instanceof Observable)
((Observable) element).addListener(this.itemListener);
return removed;
}
@Override
protected E doRemove(int index)
{
E removed = this.backingList.remove(index);
if (removed instanceof Observable)
((Observable) removed).removeListener(this.itemListener);
return removed;
}
}
import java.util.ArrayList;
导入java.util.Collection;
导入java.util.List;
导入java.util.RandomAccess;
导入javafx.beans.InvalizationListener;
导入javafx.beans.Observable;
导入javafx.collections.ModifiableObservableListBase;
导入javafx.collections.ObservableList;
公共类ObservableModelList扩展了ModifiableObservableListBase
实现可观察列表、随机访问
{
private final InvalizationListener itemListener=新的InvalizationListener()
{
@凌驾
公共无效(可观察到)
{
int index=observedModelList.this.indexOf(observeable);
如果(索引>=0)
{
ObservableModelList.this.fireChange(索引);
}
}
};
私人最终列表备份列表;
公共可观察模型列表()
{
这个(新的ArrayList());
}
公共可观察模型列表(列表)
{
this.backingList=列表;
对于(E:此.备份列表)
{
if(e可观测的实例)
((可观察的)e).addListener(this.itemListener);
}
}
@凌驾
公共E-get(int索引)
{
返回此.backingList.get(索引);
}
@凌驾
公共整数大小()
{
返回此.backingList.size();
}
@凌驾
public int indexOf(对象o)
{
返回此.backingList.indexOf(o);
}
@凌驾
公共int lastIndexOf(对象o)
{
返回此.backingList.lastIndexOf(o);
}
@凌驾
公共布尔包含(对象o)
{
返回此.backingList.contains(o);
}
@凌驾
公共布尔容器(集合c)
{
返回此.backingList.containsAll(c);
}
@凌驾
公共空间清除()
{
对于(E:此.备份列表)
{
if(e可观测的实例)
((可观察的)e).RemovelListener(this.itemListener);
}
if(hasListeners())
{
beginChange();
nextRemove(0,this);
}
这个.backingList.clear();
++这是modCount;
if(hasListeners())
{
endChange();
}
}
@凌驾
公共无效删除(int-fromIndex,int-toIndex)
{
beginChange();
for(int i=fromIndex;i 对于(int i=startIndex;我不能在
import java.util.function.Function;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.property.ReadOnlyObjectWrapper;
public class ValueWrapper<S extends Observable, T> extends ReadOnlyObjectWrapper<T> implements InvalidationListener
{
protected S parent;
protected Function<S, T> getValue;
public ValueWrapper(S parent, Function<S, T> getValue)
{
super(getValue.apply(parent));
this.parent = parent;
this.getValue = getValue;
parent.addListener(new WeakInvalidationListener(this));
}
@Override
public void invalidated(Observable observable)
{
T newValue = this.getValue.apply(this.parent);
this.setValue(newValue);
}
}