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

Removing items from ComboBox messes up selection

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      JavaFX version 15 and 16

      A DESCRIPTION OF THE PROBLEM :
      index computation and rendering of combobox has issues when removing multiple items at once with itemsProperty().get().removeAll(Collection). This is because of a difference in how the list change is computed and how the selected index is updated.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Precondition:
      - combobox with three items
      - middle item selected
      Action:
      - remove first and last item via combox.itemsProperty().get().removeAll(...) (in example: button "Trigger bug")

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      middle item stays selected and rendered, selected index is 0 (first and only item)
      ACTUAL -
      middle item stays selected, but rendered text is empty, since selected index is -1.

      ---------- BEGIN SOURCE ----------
      package test;

      import javafx.application.Application;
      import javafx.collections.FXCollections;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.ComboBox;
      import javafx.scene.layout.StackPane;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      import java.util.HashSet;
      import java.util.List;
      import java.util.Set;

      public class App extends Application {

        private ComboBox<String> comboBox;

        @Override
        public void start(Stage primaryStage) throws Exception {
          var root = new StackPane();
          var scene = new Scene(root);
          primaryStage.setScene(scene);
          var box = new VBox();
          var buttonBug = new Button();
          var buttonWorkaround = new Button();
          var buttonReset = new Button();
          comboBox = new ComboBox<>();
          comboBox.itemsProperty().set(FXCollections.observableArrayList(List.of("foo", "bar", "baz")));
          comboBox.valueProperty().set("bar");
          buttonBug.textProperty().set("Trigger bug");
          buttonBug.onActionProperty().set(e -> comboBox.itemsProperty().get().removeAll(getAllButSelected()));
          buttonWorkaround.textProperty().set("Workaround bug");
          buttonWorkaround.onActionProperty().set(e -> getAllButSelected().forEach(comboBox.itemsProperty().get()::remove));
          buttonReset.textProperty().set("Reset");
          buttonReset.onActionProperty().set(e -> {
            comboBox.itemsProperty().get().setAll("foo", "bar", "baz");
            comboBox.valueProperty().set("bar");
          });
          box.getChildren().addAll(comboBox, buttonBug, buttonWorkaround, buttonReset);
          root.getChildren().add(box);
          primaryStage.show();
        }

        private Set<String> getAllButSelected() {
          var result = new HashSet<>(comboBox.itemsProperty().get());
          var selected = comboBox.valueProperty().get();
          result.remove(selected);
          return result;
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      remove items one by one instead of with removeAll (button "Workaround bug")

      FREQUENCY : always


        1. App.java
          2 kB
        2. Capture.PNG
          Capture.PNG
          20 kB

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: