0

I'm setting up a ListView from an Observable list which has an input of another collection (in this case, a linked list). So i found in this answer how to make the items of the list view get removed from it (I'm not pretty sure if they are removed from the ObservableList as well), so theres any possible way to make the modifications in both collections (i.e. the ObservableList and the original collection)?

Here's a piece of the code:

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();
}
Chaitanya
  • 3,590
  • 14
  • 33
Eric Toporek
  • 121
  • 7
  • I believe you want [Bindings.bindContent](https://openjfx.io/javadoc/12/javafx.base/javafx/beans/binding/Bindings.html#bindContent%28java.util.List,javafx.collections.ObservableList%29). – VGR May 13 '19 at 07:17
  • Why not just have only the observable list if they are going to always be the same? – SedJ601 May 13 '19 at 12:49
  • to instantiate an observableList that's backed by the original (meaning: changing the observable modifies the original list), use https://openjfx.io/javadoc/11/javafx.base/javafx/collections/FXCollections.html#observableList(java.util.List) – kleopatra May 13 '19 at 16:18
  • @klepatra I do not understand the method's nature properly, it says that the retun will be a new Observable list, but how could this goes backwards to modify the original list? – Eric Toporek May 14 '19 at 04:38
  • @Sedrick interesting comment, mainly the reason is that the list is extracted from a Java Object, I want to keep the modules separate, but having an ObservableList could be a good option for sure. – Eric Toporek May 14 '19 at 04:40

1 Answers1

0

The short answer is no. You can update the original list based on the changes which occur in the ObservableList, but not the other way around.

The reason is that ObservableList notifies observers of changes occurred to the collection.

You can update the source list like this:

Updated

In the example below there are 3 different ways to disambiguate the lambda, you clearly should use just one.

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);
    }

}

A linked list instead, has no equivalent method to notify observers of its changes.

Method polymorphism makes the lambda syntax awkward because you can have (as in this case) the same method name with different method signatures, so you have to let the compiler know which one you are using (either by making parameters unambiguous) or literally specifying the functional interface you want to pass as lambda.

For example addListener of Observable has normally both a specific listener for the specific change of that subclass and an InvalidationListener for all, so you have to let the compiler know which of the 2 you are selecting.

minus
  • 2,646
  • 15
  • 18
  • Well that's what I'm looking for. But it seems like the code doesn't work properyly, I've got the following errors: `The method addListener(ListChangeListener) is ambiguous for the type ObservableList.` and `non-static variable cannot be referenced ...` the first one is fixed with a cast, but the second one? – Eric Toporek May 14 '19 at 04:24