本身可观察的Javafx可观察值列表?
Javafx observable list of values that are themselves observable?
现在我有以下内容:
ObservableList<Person> personsList;
我用于显示人员列表的 UI 与 personsList 相关联。
人物如下:
class Person {
Name name
// other details
List<SomeItem> list;
}
// Item is immutable, but SomeItem can mutate by setting and getting the Items
class SomeItem {
Item item
Item item2
}
问题是 SomeItem 是可变的,因此我希望将对 SomeItem 的任何更改传播到原始 personsList。
我怎样才能实现这样的目标??基于谷歌搜索,我做了以下修改,但我不确定它们是否有效!
class Person {
Name name
// other details
List<SomeItem> list; // <-- change to ObservableListValue<SomeItem>
}
// Item is immutable, but SomeItem can mutate by setting and getting the Items
class SomeItem {
Item item // <-- change to ObservablePropertyBase<Item>
Item item2 // <-- change to ObservablePropertyBase<Item>
}
据我了解,当任何 ObservablePropertyBase- 发生变化时,此更改将使 SomeItem 报告,然后 ObservableListValue
会将此更改向上传播,这将被 personsList 捕获?
编辑:问题 2:
是否可以强制刷新 personsList?假设我对特定的 SomeItem 进行了全面更新,然后我可以刷新整个 personsList?
您可以通过使用提取器创建 ObservableList
来触发 Change
事件。
这是一个例子:
Name.java:
public class Name {
private final String name;
public Name(String name) {
this.name = name;
}
public final String getName() {
return name;
}
}
Item.java:
public class Item {
private final String name;
public Item(String name) {
this.name = name;
}
public final String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
一些Item.java:
public class SomeItem {
private final ObjectProperty<Item> item1 = new SimpleObjectProperty<>(this, "item1");
private final ObjectProperty<Item> item2 = new SimpleObjectProperty<>(this, "item2");
public SomeItem(Item item1, Item item2) {
this.item1.set(item1);
this.item2.set(item2);
}
public final ObjectProperty<Item> item1Property() {
return item1;
}
public final Item getItem1() {
return item1.get();
}
public final void setItem1(Item item) {
item1.set(item);
}
public final ObjectProperty<Item> item2Property() {
return item2;
}
public final Item getItem2() {
return item2.get();
}
public final void setItem2(Item item) {
item2.set(item);
}
@Override
public String toString() {
return "[" + item1.get() + ", " + item2.get() + "]";
}
}
Person.java:
public class Person {
private final Name name;
private final ObservableList<SomeItem> someItems = FXCollections.observableArrayList(someItem ->
new Observable[]{someItem.item1Property(), someItem.item2Property()});
public Person(Name name, SomeItem... someItems) {
this.name = name;
this.someItems.addAll(someItems);
}
public final Name getName() {
return name;
}
public final ObservableList<SomeItem> getSomeItems() {
return someItems;
}
@Override
public String toString() {
return "[name=" + name.getName() + ", someItems=" + someItems + "]";
}
}
App.java:
public class App extends Application {
@Override
public void start(Stage stage) {
SomeItem someItem1 = new SomeItem(new Item("item1"), new Item("item2"));
SomeItem someItem2 = new SomeItem(new Item("item3"), new Item("item4"));
SomeItem someItem3 = new SomeItem(new Item("item5"), new Item("item6"));
SomeItem someItem4 = new SomeItem(new Item("item7"), new Item("item8"));
Person person1 = new Person(new Name("person1"), someItem1, someItem2);
Person person2 = new Person(new Name("person2"), someItem3, someItem4);
ObservableList<Person> persons = FXCollections.observableArrayList(person ->
new Observable[]{person.someItemsProperty()});
persons.addAll(person1, person2);
persons.addListener((ListChangeListener<Person>) c -> {
while (c.next()) {
if (c.wasUpdated()) {
System.out.println("Updated persons:");
IntStream.range(c.getFrom(), c.getTo())
.mapToObj(index -> "Person at index " + index + " was updated to: " + c.getList().get(index))
.forEach(System.out::println);
}
}
});
// Update items to trigger change event for testing
someItem1.setItem1(new Item("item1Updated"));
someItem4.setItem2(new Item("item8Updated"));
}
public static void main(String[] args) {
launch();
}
}
输出:
Updated persons:
Person at index 0 was updated to: [name=person1, someItems=[[item1Updated, item2], [item3, item4]]]
Updated persons:
Person at index 1 was updated to: [name=person2, someItems=[[item5, item6], [item7, item8Updated]]]
现在我有以下内容:
ObservableList<Person> personsList;
我用于显示人员列表的 UI 与 personsList 相关联。
人物如下:
class Person {
Name name
// other details
List<SomeItem> list;
}
// Item is immutable, but SomeItem can mutate by setting and getting the Items
class SomeItem {
Item item
Item item2
}
问题是 SomeItem 是可变的,因此我希望将对 SomeItem 的任何更改传播到原始 personsList。
我怎样才能实现这样的目标??基于谷歌搜索,我做了以下修改,但我不确定它们是否有效!
class Person {
Name name
// other details
List<SomeItem> list; // <-- change to ObservableListValue<SomeItem>
}
// Item is immutable, but SomeItem can mutate by setting and getting the Items
class SomeItem {
Item item // <-- change to ObservablePropertyBase<Item>
Item item2 // <-- change to ObservablePropertyBase<Item>
}
据我了解,当任何 ObservablePropertyBase
编辑:问题 2: 是否可以强制刷新 personsList?假设我对特定的 SomeItem 进行了全面更新,然后我可以刷新整个 personsList?
您可以通过使用提取器创建 ObservableList
来触发 Change
事件。
这是一个例子:
Name.java:
public class Name {
private final String name;
public Name(String name) {
this.name = name;
}
public final String getName() {
return name;
}
}
Item.java:
public class Item {
private final String name;
public Item(String name) {
this.name = name;
}
public final String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
一些Item.java:
public class SomeItem {
private final ObjectProperty<Item> item1 = new SimpleObjectProperty<>(this, "item1");
private final ObjectProperty<Item> item2 = new SimpleObjectProperty<>(this, "item2");
public SomeItem(Item item1, Item item2) {
this.item1.set(item1);
this.item2.set(item2);
}
public final ObjectProperty<Item> item1Property() {
return item1;
}
public final Item getItem1() {
return item1.get();
}
public final void setItem1(Item item) {
item1.set(item);
}
public final ObjectProperty<Item> item2Property() {
return item2;
}
public final Item getItem2() {
return item2.get();
}
public final void setItem2(Item item) {
item2.set(item);
}
@Override
public String toString() {
return "[" + item1.get() + ", " + item2.get() + "]";
}
}
Person.java:
public class Person {
private final Name name;
private final ObservableList<SomeItem> someItems = FXCollections.observableArrayList(someItem ->
new Observable[]{someItem.item1Property(), someItem.item2Property()});
public Person(Name name, SomeItem... someItems) {
this.name = name;
this.someItems.addAll(someItems);
}
public final Name getName() {
return name;
}
public final ObservableList<SomeItem> getSomeItems() {
return someItems;
}
@Override
public String toString() {
return "[name=" + name.getName() + ", someItems=" + someItems + "]";
}
}
App.java:
public class App extends Application {
@Override
public void start(Stage stage) {
SomeItem someItem1 = new SomeItem(new Item("item1"), new Item("item2"));
SomeItem someItem2 = new SomeItem(new Item("item3"), new Item("item4"));
SomeItem someItem3 = new SomeItem(new Item("item5"), new Item("item6"));
SomeItem someItem4 = new SomeItem(new Item("item7"), new Item("item8"));
Person person1 = new Person(new Name("person1"), someItem1, someItem2);
Person person2 = new Person(new Name("person2"), someItem3, someItem4);
ObservableList<Person> persons = FXCollections.observableArrayList(person ->
new Observable[]{person.someItemsProperty()});
persons.addAll(person1, person2);
persons.addListener((ListChangeListener<Person>) c -> {
while (c.next()) {
if (c.wasUpdated()) {
System.out.println("Updated persons:");
IntStream.range(c.getFrom(), c.getTo())
.mapToObj(index -> "Person at index " + index + " was updated to: " + c.getList().get(index))
.forEach(System.out::println);
}
}
});
// Update items to trigger change event for testing
someItem1.setItem1(new Item("item1Updated"));
someItem4.setItem2(new Item("item8Updated"));
}
public static void main(String[] args) {
launch();
}
}
输出:
Updated persons:
Person at index 0 was updated to: [name=person1, someItems=[[item1Updated, item2], [item3, item4]]]
Updated persons:
Person at index 1 was updated to: [name=person2, someItems=[[item5, item6], [item7, item8Updated]]]