【问题标题】:Javafx observable list of values that are themselves observable?Javafx 可观察的值列表,这些值本身是可观察的?
【发布时间】:2021-12-07 03:45:01
【问题描述】:

现在我有以下内容:

ObservableList<Person> personsList;

我用于显示人员列表的 UI 与 personList 相关联。

人物如下:

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 的任何更改都传播到原始的 peopleList。

我将如何实现这样的目标?根据谷歌搜索,我有以下修改,但我不确定它们是否有效!

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 将向上传播此更改,这将被 personList 捕获?

编辑:问题 2: 是否可以强制刷新personsList?假设我对特定的 SomeItem 进行了整体更新,然后我可以刷新整个 peopleList?

【问题讨论】:

  • 每个问题一个问题,请提供一个minimal reproducible example 来说明您迄今为止所尝试的内容(如果您知道 Person 中的列表字段应该是可观察的,那么要走的路就是让它的类型为 observableList :) 让 someItem 至少将其属性公开为 .. 以及 observableValues 并在 Person 中配置 observableList 并在这些 observables 上使用提取器(然后,只要观察到 someItem 的属性,该列表就会使用 wasUpdated 类型的更改事件通知其侦听器已更改。
  • 我同意 kleopatra 的观点。这些都是不错的问题,并且会得到回答,但最好将它们作为单独的问题,每个问题都有一个特定的minimal reproducible example(例如,可以复制和粘贴的完整代码,无需更改即可复制问题)。另外,您能否解释一下“对 SomeItem 的更改将传播到原始的 peopleList”,这到底是什么意思(如果您愿意,您可以再次澄清对问题的编辑)。
  • 例如,为您的问题编写(失败的)文本案例(它不会有任何 UI)并将其代码放入问题中。然后有人可以发布并回答调整代码以使其按预期工作并且测试将通过。
  • 剂量this回答你的问题之一?

标签: java javafx javafx-8


【解决方案1】:

您可以通过使用提取器创建ObservableList 来触发Change 事件。

这是一个例子:

名称.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;
    }

}

SomeItem.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]]]

【讨论】:

    猜你喜欢
    • 2016-10-20
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    相关资源
    最近更新 更多