将对ObservableList的修改合并到原始集合

时间:2019-05-13 06:42:48

标签: java list javafx collections

我正在从一个Observable列表设置一个ListView,该列表具有另一个集合的输入(在本例中为链接列表)。因此,我在this answer中找到了如何从中删除列表视图中的项目的方法(我不太确定它们是否也从ObservableList中删除了),因此有任何可能的方法可以在其中进行修改这两个集合(即ObservableList和原始集合)?

下面是一段代码:

LinkedList<> shoppingCart; //In the code this has been initialized before.

public static class XCell extends ListCell<Product> {
    HBox hb = new HBox();
    Label name = new Label("");
    Pane p = new Pane();
    Button d = new Button("X");

    public XCell() {
        super();
        File f = new File("src/style/main.css");
        hb.getStylesheets().clear();
        hb.getStylesheets().add("file:///" + f.getAbsolutePath().replace("\\", "/"));
        hb.getChildren().addAll(nombre, p, d);
        HBox.setHgrow(p, Priority.ALWAYS);
        d.getStyleClass().add("red-btn");
        d.setOnAction(event -> getListView().getItems().remove(getItem()));

    }

    @Override
    protected void updateItem(Product item, boolean empty) {
        super.updateItem(item,empty);
        setText(null);
        setGraphic(null);

        if (item != null && !empty) {
            nombre.setText(item.toString());
            setGraphic(hb);
        }

    }
}

private void showCart(ActionEvent event){
   ObservableList<Product> cart = FXCollections.observableArrayList(shoppingCart);
   ListView<Alimento> lv = new ListView<>(cart);
   lv.setCellFactory(param -> new XCell());
   Scene sc = new Scene(lv);
   Stage st = new Stage();
   st.setScene(sc);
   st.setTitle("Pizza! -- Cart");
   st.show();
}

1 个答案:

答案 0 :(得分:0)

简短的回答是“否”。您可以根据ObservableList中发生的更改来更新原始列表,但不能反过来。

原因是ObservableList将集合发生的更改通知观察者

您可以像这样更新源列表:

已更新

在下面的示例中,有3种方法可以消除lambda的歧义,您显然应该只使用一种。

public class SomeController {

    public class SomeObject {}

    private List<SomeObject> sourceList;

    @FXML
    private ListView<SomeObject> aView;

    public void init(){

        aView.getItems().addAll(sourceList);

        // You can use method (which is strictly typed)
        aView.getItems().addListener(this::updateSource);

        // You can specify the type of the arguments
        aView.getItems().addListener((Change<? extends SomeObject> changes)->{
            ObservableList<? extends SomeObject> lst = changes.getList();
            sourceList.clear();
            sourceList.addAll(lst);
        });

        // You can specify the type of the functional interface
        aView.getItems().addListener((ListChangeListener<SomeObject>) changes->{
            ObservableList<? extends SomeObject> lst = changes.getList();
            sourceList.clear();
            sourceList.addAll(lst);
        });
    }

    private void updateSource(Change<? extends SomeObject> chg) {
        ObservableList<? extends SomeObject> data = chg.getList();
        sourceList.clear();
        sourceList.addAll(data);
    }

}

相反,链表没有等效的方法将其更改通知观察者

方法多态性使 lambda 语法很尴尬,因为您可以(在这种情况下)具有不同方法签名的相同方法名称,因此必须让编译器知道您使用的是哪个( (通过使参数明确)或从字面上指定要作为lambda传递的功能接口。

例如,Observable的addListener通常既具有针对该子类的特定更改的特定侦听器,又具有针对所有子类的InvalidationListener的侦听器,因此您必须让编译器知道您选择的是哪两个。