【问题标题】:Why the behavior for ChangeListener<T> is different depending on the T parameter为什么 ChangeListener<T> 的行为因 T 参数而异
【发布时间】:2016-01-14 15:56:19
【问题描述】:

考虑以下程序:

import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;

/**
 *
 * @author kachna
 */
public class ListPropertyTest {

    public static void main(String[] args) {
        StringProperty p = new SimpleStringProperty();
        p.addListener((obs, old, nw) -> {
            System.out.println("String Property; oldString: " + old + ", newString: " + nw);
        });
        p.set("1");

        ListProperty<String> listProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
        listProperty.addListener((obs, old, nw) -> {
            System.out.println("ListProperty; oldList:  " + old + ", newList: " + nw);

        });

        listProperty.addAll("1", "2", "3");

    }
}

运行程序给出以下输出:

String Property; oldString: null, newString: 1
ListProperty; oldList:  [1, 2, 3], newList: [1, 2, 3]

如您所见,旧值为:

  1. nullTString
  2. T 是一个等于新值的值 ObservableList&lt;String&gt;

【问题讨论】:

  • 对我来说似乎是可变数据的一般问题。当你改变它的内容时,列表实例相同的,所以旧值和新值是对同一个列表的引用,但是由于通知是在修改之后发生的,所以列表显示新的内容,不管当然,您使用哪个参考来访问它。
  • 我调试了它,看起来这来自com.sun.javafx.binding.ListExpressionHelper.fireValueChangedEvent(change)。此方法赋予旧值和新值相同的值。

标签: java-8 javafx-8


【解决方案1】:

这是一个错误:ListProperty 在包装列表的内容更改时根本不应该触发更改的事件:它应该只触发列表更改的事件。换句话说,您应该只能检测到来自

的更改
listProperty.addAll("1", "2", "3");

与听众一起

listProperty.addListener((ListChangeListener<? extends String> change) -> {
    // e.g.
    while (change.next()) {
        if (change.wasAdded()) {
            System.out.println(change.getAddedSubList());
        }
    }
});

您注册的侦听器应仅在您更改实际引用时触发,例如与

listProperty.setValue(FXCollections.observableArrayList("1","2","3"));

这可能是一个在不破坏大量现有代码的情况下无法修复的错误:我不知道是否有计划纠正这个问题。

实际发生的是 change 事件被触发,但旧值和新值引用同一个列表(因为实际包装的列表引用没有改变)。所以,当然,toString() 方法无论从old 还是nw 调用都返回相同的值,并给出列表的当前内容。

【讨论】:

  • 我认为你的推理是正确的。但我已阅读以下内容(来自 Learn Javafx8 电子书):When the content of the list changes, the changed() method of ChangeListeners receives the reference to the same list as the old and new value. If the wrapped reference of the ObservableList is replaced with a new one, this method receives references of the old list and the new list.
  • 是的,好的,和我说的基本一样。但是,我认为不应该在第一种情况下触发该事件,因为包装的引用没有改变。
猜你喜欢
  • 1970-01-01
  • 2012-09-04
  • 2020-09-19
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 2020-02-10
  • 2011-05-12
  • 2011-02-24
相关资源
最近更新 更多