ListView using custom factory cell does not update after deleting items

I am learning JavaFX and I need to create a factory cell that works correctly until I want to remove a row from my ListView :

 plateList.setCellFactory(new Callback<ListView<Car>, ListCell<Car>>() { @Override public ListCell<Car> call(ListView<Car> param) { ListCell<Car> cell = new ListCell<Car>() { @Override protected void updateItem(Car item, boolean empty) { super.updateItem(item, empty); if (item != null) { setText(item.getPlate()); } } }; return cell; } }); 

I populate the ListView few data examples:

 ObservableList<Car> sample = FXCollections.observableArrayList(); sample.add(new Car("123-abc", "opel", "corsa", 5.5)); sample.add(new Car("123-cba", "vw", "passat", 7.5)); plateList.setItems(sample); 

Now I will see that I expect the ListView be as follows:

  • 123-abc
  • 123-CBA

However, if you delete the line ex: the first line (123-abc), the ListView will look like this:

  • 123-CBA
  • 123-CBA

This is part of the removal:

 @FXML private void deleteBtnAction() { plateList.getItems().remove(plateList.getSelectionModel().getSelectedItem()); ObservableList<Car> t = plateList.getItems(); plateList.setItems(t); } 

If I delete the factory cell, the program works as intended. Any help is appreciated.

+6
source share
2 answers

Try moving on to the following: This is necessary since JavaFX reuses list cells, so updateItem () should also use empty unused characters when passing null

 super.updateItem(item, empty); if (item != null) { setText(item.getPlate()); } else { setText(""); // <== clear the now empty cell. } 

Full SSCCE

 import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.util.Callback; public class JavaFxListView extends Application { private static class Car { private String plate; public Car(String plate, String string2, String string3, double d) { this.plate = plate; } public String getPlate() { return plate; } } public static void main(String[] args) { launch(args); } @Override public void start(Stage arg0) throws Exception { ListView<Car> plateList = new ListView<Car>(); plateList.setCellFactory(new Callback<ListView<Car>, ListCell<Car>>() { @Override public ListCell<Car> call(ListView<Car> param) { ListCell<Car> cell = new ListCell<Car>() { @Override protected void updateItem(Car item, boolean empty) { super.updateItem(item, empty); if (item != null) { setText(item.getPlate()); } else { setText(""); } } }; return cell; } }); Button delete = new Button("Delete"); ObservableList<Car> sample = FXCollections.observableArrayList(); sample.add(new Car("123-abc", "opel", "corsa", 5.5)); sample.add(new Car("123-cba", "vw", "passat", 7.5)); delete.setOnAction((e) -> { plateList.getItems().remove(plateList.getSelectionModel().getSelectedItem()); ObservableList<Car> t = plateList.getItems(); plateList.setItems(t); }); plateList.setItems(sample); arg0.setScene(new Scene(new VBox(plateList, delete))); arg0.show(); } } 
+11
source

According to the Java Cell document updateItem, there is a slightly different recommended use than accepted:

  protected void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); } else { setText(item.toString()); } } 

The difference is in using the empty parameter. But sollution from @Adam should work correctly in the main cases.

+4
source

Source: https://habr.com/ru/post/982135/


All Articles