我有一些我不明白结果的代码:
ObservableList<Integer> li = FXCollections.observableArrayList();
li.add(1);
li.add(2);
IntegerProperty intProp = new SimpleIntegerProperty(5);
li.add(intProp.getValue());
li.add(li.get(0) + li.get(2));
System.out.println(li);
li.addListener((ListChangeListener<Integer>) change -> {
li.set(3, li.get(0) + li.get(2));
});
intProp.setValue(3);
System.out.println(intProp.get());
System.out.println(li.get(2));
System.out.println(li);
我不明白为什么更改intProp的值不会影响observableList,我的意思是位置2中的int应该是属性的值,因此第二个和第三个sysout必须相同,并且首先必须与最后一个不同,但这不是事实,它给了我:
[1, 2, 5, 6]
3
5
[1, 2, 5, 6]
我尝试通过编写以下代码进行一些更改:
ObservableList<Integer> li = FXCollections.observableArrayList();
li.add(1);
li.add(2);
li.add(5);
li.add(li.get(0) + li.get(2));
System.out.println(li);
li.addListener((ListChangeListener<Integer>) change -> {
li.set(3, li.get(0) + li.get(2));
});
li.set(2, 3);
System.out.println(li);
它显然有效,但它给了我许多我不理解的错误。
谢谢!
答案 0 :(得分:1)
从根本上讲,您似乎期望以下几点:
IntegerProperty property = new SimpleIntegerProperty(5);
int i = property.get();
property.set(10);
System.out.println(i);
打印出10
而不是5
。在Java中,因为Java is always pass-by-value,所以不会发生这种情况。将值添加到ObservableList
时也是如此;您所做的全部工作就是获取当时属性的值,并将其添加到列表中。之后,该属性和列表是完全独立的实体。
没有观察Java变量变化的基本方法。为了通知更改,必须有实现该行为的代码。 IntegerProperty
基本上只是int
周围的包装器,它拦截更改值的代码并将更改通知给观察者。像这样:
public void set(int newValue) {
this.value = newValue;
notifyObservers();
}
注意:IntegerProperty
的实际实现要复杂得多。
ObservableList
也是如此。所有的核心实现都只是常规List
的包装,而ObservableList
只是拦截调用并通知观察者更改。这就是为什么,如果您使用List
包装自己的FXCollections.observableList(List)
,则无法再直接修改List
,因为它绕过了包装ObservableList
,因此不会发生更改事件被解雇。
如果您想在ObservableList
更改时更新IntegerProperty
,则必须向IntegerProperty
添加一个侦听器,以适当地更新ObservableList
。如果要通过ObservableList
了解对包含元素的更改,则需要使用an extractor-请参阅this answer。
它显然有效,但它给了我许多我不理解的错误。
忽略“ 显然有效”和“ 给我很多错误”之间的矛盾,您实际上并没有提供所得到的错误。没有这些错误,很难知道出了什么问题。但是,您遇到以下情况(可能与您的错误有关,也可能与您的错误无关):
li.addListener((ListChangeListener<Integer>) change -> {
li.set(3, li.get(0) + li.get(2));
});
这正在修改引发更改事件的ObservableList
。您must not do this:
警告::此类直接访问源列表以获取有关更改的信息。
当列表上发生另一个更改时,这有效地使Change对象无效。
因此,在其他线程上使用此类是不安全的。
这也意味着无法在侦听器内部修改源列表,因为这会使所有后续侦听器的Change对象失效。