JavaFX的:ListView控件的更新如果ObservableList变化的元素 [英] JavaFX: Update of ListView if an element of ObservableList changes

查看:892
本文介绍了JavaFX的:ListView控件的更新如果ObservableList变化的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想显示的人员名单(的POJO中实现$ C $光盘,包含姓名属性)使用JavaFX的ListView控件。我创建了ListView和添加为ObservableList人员名单。如果我删除或添加一个新的人去ObservableList,他们却在POJO的改变不会触发ListView中的更新,一切工作正常。
我不得不删除并从ObservableList添加修改POJO触发的ListView的更新。
是否有可能没有上述的变通方法来显示的POJO中实现的变化?

I would like to display a list of persons (coded in POJOS, and containing a name and surname property) using a JavaFX ListView control. I created the ListView and added the list of persons as an ObservableList. Everything works fine if I delete or add a new person to the ObservableList, but changes in the POJO do not trigger an update of the ListView. I have to remove and add the modified POJO from the ObservableList to trigger the update of the ListView. Is there any possibility to display changes in POJOS without the workaround described above?

推荐答案

有几个方面你的问题(我并不完全是:-)我会假设你的POJO莫名其妙地通知有关改变听众的问题,可能是由是羽翼丰满的JavaBean,这是通过在需要射击的propertyChange事件或其他方式符合其合同的通知 - 否则,你将需要改变一些手动推反正

There are several aspects to your question (and I'm not entirely which is the problem :-) I'll assume that your POJO somehow notifying listeners about changes, could be by being a full-fledged JavaBean, that is complies to its notification contract via firing propertyChange events as needed or some other means - otherwise, you would need some manual push of the change anyway.

的基本方法作出FX-ObservableList上所包含的元素突变通知自己的听众是一个自定义的回调提供了观测量的阵列配置。如果元素有FX-属性,你会做这样的事情:

The basic approach to make an FX-ObservableList notify its own listeners on mutations of contained elements is to configure it with a custom Callback that provides an array of Observables. If the elements have fx-properties you would do something like:

Callback<Person, Observable[]> extractor = new Callback<Person, Observable[]>() {

    @Override
    public Observable[] call(Person p) {
        return new Observable[] {p.lastNameProperty(), p.firstNameProperty()};
    }
};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list

如果该POJO是,一个成熟的核心的javaBean,其属性必须适应于FX-性能,f.i.通过使用JavaBeanProperty:

If the pojo is-a full-fledged core javaBean, its properties have to be adapted to fx-properties, f.i. by using JavaBeanProperty:

Callback<PersonBean, Observable[]> extractor = new Callback<PersonBean, Observable[]>() {
    List<Property> properties = new ArrayList<Property>();
    @Override
    public Observable[] call(PersonBean arg0) {
        JavaBeanObjectProperty lastName = null;
        JavaBeanObjectProperty age = null;
        try {
            lastName = JavaBeanObjectPropertyBuilder.create()
                    .bean(arg0).name("lastName").build();
            age = JavaBeanObjectPropertyBuilder.create()
                    .bean(arg0).name("age").build();
            // hack around loosing weak references ... 
            properties.add(age);
            properties.add(lastName);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return new Observable[] {lastName, age};
    }

};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list

请注意一个警告:不保持一个强大的参考适应性能的地方,他们将很快垃圾收集 - 再出现一次又一次在所有(落入圈套没有任何影响,不知道如何,如果有一个很好的策略,以避免它)。

Note a caveat: without keeping a strong reference to the adapted properties somewhere, they will be quickly garbage-collected - and then appear to have no effect at all (falling into the trap again and again, not sure how if there's a good strategy to avoid it).

有关(可能粗粒度)通知任何其他手段,可以实现自定义适配器:下面的适配器听一个bean的所有propertyChanges,听其他类型的事件将是相当类似的。

For any other means of (possibly coarse-grained) notification, you can implement a custom adapter: the adapter below listens to all propertyChanges of a bean, listening to other types of events would be quite analogous.

/**
 * Adapt a Pojo to an Observable.
 * Note: extending ObservableValue is too much, but there is no ObservableBase ...
 *
 * @author Jeanette Winzenburg, Berlin
 */
public class PojoAdapter<T> extends ObservableValueBase<T> {

    private T bean;
    private PropertyChangeListener pojoListener;
    public PojoAdapter(T pojo) {
        this.bean = pojo;
        installPojoListener(pojo);
    }

    /**
     * Reflectively install a propertyChangeListener for the pojo, if available.
     * Silently does nothing if it cant.
     * @param item
     */
    private void installPojoListener(T item) {
        try {
            Method method = item.getClass().getMethod("addPropertyChangeListener", 
                  PropertyChangeListener.class);
            method.invoke(item, getPojoListener());
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | 
                  IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    /**
     * Returns the propertyChangeListener to install on each item.
     * Implemented to call notifyList.
     * 
     * @return
     */
    private PropertyChangeListener getPojoListener() {
        if (pojoListener == null) {
            pojoListener = new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    fireValueChangedEvent();
                }
            };
        }
        return pojoListener;
    }

    @Override
    public T getValue() {
        return bean;
    }

}

它的使用只是同上(越来越无聊,是不是: - )

It's usage just the same as above (getting boring, isn't it :-)

Callback<PersonBean, Observable[]> extractor = new Callback<PersonBean, Observable[]>() {

    @Override
    public Observable[] call(PersonBean arg0) {
        return new Observable[] {new PojoAdapter<PersonBean>(arg0)};
    }

};
ObservableList<Person> teamMembers = FXCollections.observableArrayList(extractor);
// fill list

不幸的是,这种凉爽的列表中的ListView的自动更新将不可靠的,由于只固定了一个工作的bug在jdk8 。在早期版本中,你又回到广场1 - 莫名其妙地听着变化,然后手动更新列表:

Unfortunately, automatic updates of a ListView with such cool list won't work reliably due to a bug that's fixed only in jdk8. In earlier versions, you are back at square 1 - somehow listening to the change and then manually update the list:

protected void notifyList(Object changedItem) {
    int index = list.indexOf(changedItem);
    if (index >= 0) {
        // hack around RT-28397
        //https://javafx-jira.kenai.com/browse/RT-28397
        list.set(index, null);
        // good enough since jdk7u40 and jdk8
        list.set(index, changedItem);
    }
}

这篇关于JavaFX的:ListView控件的更新如果ObservableList变化的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆