Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
370 views
in Technique[技术] by (71.8m points)

java - ListView using custom cell factory doesn't update after items deleted

I'm learning JavaFX and i wanted to create a cell factory which is working properly until i want to delete 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'm populating the ListView with some sample data:

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 what i expect the ListView will be the following:

  • 123-abc
  • 123-cba

How ever if delete a row ex: the first row (123-abc), the ListView will look like this:

  • 123-cba
  • 123-cba

This is the delete part:

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

If i remove the cell factory the program works as intended. Any help is greatly appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Try changing to the following, This is required as JavaFX reuses the list cells, so the updateItem() needs to blank unused ones too when passed 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();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...