Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX:可观察模型/列表&;自动用户界面刷新_Java_Javafx_Observable - Fatal编程技术网

JavaFX:可观察模型/列表&;自动用户界面刷新

JavaFX:可观察模型/列表&;自动用户界面刷新,java,javafx,observable,Java,Javafx,Observable,几天来,我一直在尝试让用户界面自动刷新工作与WPF一样,老实说,我对在谷歌上找到的解决方案非常不满意,因为它们大多是黑客/变通方法 我想要的是: 模型列表中的更改会导致UI更改 模型属性的更改会导致UI更改 模型属性的更改会传播到包含列表并导致UI更改 以下是我目前的情况: 模型类必须基于ObservaleModel 模型类支持手动触发属性更改(还没有自动触发) 模型列表支持自动触发集合更改和包含项中发生的属性更改 ListView可以直接使用ObservableModelList Tabl

几天来,我一直在尝试让用户界面自动刷新工作与WPF一样,老实说,我对在谷歌上找到的解决方案非常不满意,因为它们大多是黑客/变通方法

我想要的是:

  • 模型列表中的更改会导致UI更改
  • 模型属性的更改会导致UI更改
  • 模型属性的更改会传播到包含列表并导致UI更改
以下是我目前的情况:

  • 模型类必须基于ObservaleModel
  • 模型类支持手动触发属性更改(还没有自动触发)
  • 模型列表支持自动触发集合更改和包含项中发生的属性更改
  • ListView可以直接使用ObservableModelList
  • TableView要求每个TableColumn都具有cellValueFactory设置,例如

    cell.setTableValueFactory(cell->new ValueWrapper(cell.getValue(),m->m.getProperty())

  • 现在的问题是:

  • 我应该担心内存泄漏吗?有几个弱事件侦听器,但如果它们是通用的,为什么JavaFX不在内部将所有侦听器包装为弱侦听器呢
  • 更新性能:JavaFX是否会自动延迟/批处理更新,或者我必须在beginChange()…endChange()中包含更改事件触发?如果是,我可以让所有属性设置器触发无效事件,并使事情变得更简单
  • 可观察模型:

    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);
        }
    }