Issue
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();
}
Solution
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.
Answered By - minus