Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8095003

[ListView] Deleting items from ListView with setCellFactory causes unexpected displaying behaviour

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • 8u20
    • 8u5
    • javafx
    • Windows 7. JDK 8.

      The observed problem:
      I want to use a ListView to display complex objects. In the code below I used a simple StringWrapper Class to simulate the observed behaviour. When an item is deleted from the ListView, though internaly it is removed from the associated ObservableList, the user will still be shown the item in the list. However that item will not be selectable anymore. In fact, the list will always show the same amount of items (in the end very random items) until the last item has been deleted. With the deletion of the last item the list will be cleared.

      The Problem only occurs when an own CellFactory is used. Furthermore, the same code runs just fine with JDK 7.

      Here is the Code:

      package listviewbug;

      import java.util.ArrayList;
      import javafx.application.Application;
      import javafx.collections.FXCollections;
      import javafx.collections.ObservableList;
      import javafx.event.ActionEvent;
      import javafx.fxml.FXML;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.ListCell;
      import javafx.scene.control.ListView;
      import javafx.scene.layout.FlowPane;
      import javafx.scene.layout.Pane;
      import javafx.scene.layout.VBox;
      import javafx.scene.text.Text;
      import javafx.stage.Stage;

      /**
       *
       * @author me
       */
      public class ListViewBug extends Application {

          @FXML
          ListView<StringWrapper> listView;
          @FXML
          Button removeButton;

          ObservableList<StringWrapper> stringList;

          @Override
          public void start(Stage primaryStage) {
              
              //create a new ListView
              listView = new ListView();
              listView.autosize();
              
              //intial set up for the example ListView
              fillList();
              
              //button to delete items from the list
              Button bt_delete = new Button();
              bt_delete.setText("delete selected");
              bt_delete.setOnAction((ActionEvent event) -> {
                  if (listView.getSelectionModel().getSelectedIndex() == -1) {
                      System.out.println("NOTHING SELECTED!");
                  } else {
                      stringList.remove(listView.getSelectionModel().getSelectedItem());
                      printInfo();
                  }
              });
              
              //button to fill list up again, start test over.
              Button bt_fillList = new Button();
              bt_fillList.setText("fill list");
              bt_fillList.setOnAction((ActionEvent event) -> fillList());
              

              //add elements to stack pane
              FlowPane root = new FlowPane();
              VBox vbox = new VBox(bt_delete, bt_fillList);
              root.getChildren().add(vbox);
              root.getChildren().add(new Pane(listView));

              Scene scene = new Scene(root, 400, 250);

              primaryStage.setTitle("ListView Bug");
              primaryStage.setScene(scene);
              primaryStage.show();
          }
          
          /**
           * Fills list with some example StringWrappers
           */
          public void fillList() {
              //Create some test StringWrapper
              ArrayList<StringWrapper> StringWrapper = new ArrayList();
              StringWrapper.add(new StringWrapper("a"));
              StringWrapper.add(new StringWrapper("b"));
              StringWrapper.add(new StringWrapper("c"));
              StringWrapper.add(new StringWrapper("d"));
              StringWrapper.add(new StringWrapper("e"));

              //add StringWrapper to an ObservableList
              stringList = FXCollections.observableArrayList(StringWrapper);
              //set items of the ObservableList for the ListView
              listView.setItems(stringList);

              //set how the StringWrapper will be displayed
              listView.setCellFactory((ListView<StringWrapper> p) -> new StringWrapperEventCell());

              printInfo();
          }
          
          /**
           * A ListCell displaying a StringWrapper. The List Wrapper is simply
           * converted to a String and then put into a Text object.
           */
          private static class StringWrapperEventCell extends ListCell<StringWrapper> {

              @Override
              protected void updateItem(StringWrapper se, boolean bln) {
                  super.updateItem(se, bln); //To change body of generated methods, choose Tools | Templates.
                  if (se != null) {
                      Text t = new Text(se.toString());
                      setGraphic(t);
                  }
              }
          }

          /**
           * @param args the command line arguments
           */
          public static void main(String[] args) {
              launch(args);
          }

          /**
           * StringWrapper Class to represent a complex Object.
           */
          public class StringWrapper {

              String string;

              public StringWrapper(String string) {
                  this.string = string;
              }

              @Override
              public String toString() {
                  return string;
              }

          }

          public void printInfo() {
              System.out.println("+++++++++++++++++++++++++++++++");
              System.out.println("ListView Size: " + listView.getItems().size());
              System.out.println("ObservableList Size: " + stringList.size());
              System.out.println("+++++++++++++++++++++++++++++++");

          }

      }
      </AnchorPane>

            jgiles Jonathan Giles
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: