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

JavaFX TableView ComboBoxTableCell cell item is updated on table scroll

XMLWordPrintable

    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      1.8.0_141

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows Version 6.1.7601

      A DESCRIPTION OF THE PROBLEM :
      Selected editable combo-box cell value is altered on table scroll when the row is scroll off-screen if the selected value is not the first element in the combo-box list.


      Suspect this bug has existed for some time.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      To reproduce:
      - find a cell where a value other that first value in the combo-box list is present (i.e. the second or third value in the list)
      - click on a combo-box cell twice to get the combobox component to show (but do not click a third time to open the combo-box popup.
      - move the mouse cursor away from the combo-box, and scroll the table with the mouse wheel so that the selected record is off screen
      - scroll back up and the value has changed to the first element in the combo-box list.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expect the property value not to change.
      ACTUAL -
      TableCell#updateItem() is erroneously invoked with the new value.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.blah;

      import java.util.Random;
      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      import javafx.scene.Scene;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.ComboBoxTableCell;
      import javafx.scene.control.cell.TextFieldTableCell;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;

      public class TableWithComboBoxExample extends Application {

          @Override
          public void start(Stage primaryStage) {
              TableView<Contact> contactTable = new TableView<>();
              contactTable.setEditable(true);

              TableColumn<Contact, String> nameCol = new TableColumn<>("Name");
              nameCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
              nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
              contactTable.getColumns().add(nameCol);

              String[] strings = {"Friends", "Family", "Work Contacts"};

              TableColumn<Contact, String> categoryCol = new TableColumn<>("Category");
              categoryCol.setCellValueFactory(cellData -> cellData.getValue().categoryProperty());
              categoryCol.setCellFactory(ComboBoxTableCell.forTableColumn(strings));
              contactTable.getColumns().add(categoryCol);

              contactTable.getItems().addAll(
                      new Contact("Bill Gates", "Work Contacts"),
                      new Contact("Barack Obama", "Friends"),
                      new Contact("Tim Cook", "Work Contacts")
              );

              Random random = new Random();
              for (int i = 0; i < 500; i++) {
                  contactTable.getItems().add(new Contact(Integer.toString(i), strings[random.nextInt(strings.length)]));
              }

              Scene scene = new Scene(new BorderPane(contactTable), 600, 600);
              primaryStage.setScene(scene);
              primaryStage.show();
          }

          public static class Contact {

              private final StringProperty name = new SimpleStringProperty();
              private final StringProperty category = new SimpleStringProperty();

              public Contact(String name, String category) {
                  setName(name);
                  setCategory(category);
              }

              public final StringProperty nameProperty() {
                  return this.name;
              }

              public final String getName() {
                  return this.nameProperty().get();
              }

              public final void setName(final String name) {
                  this.nameProperty().set(name);
              }

              public final StringProperty categoryProperty() {
                  return this.category;
              }

              public final String getCategory() {
                  return this.categoryProperty().get();
              }

              public final void setCategory(final String category) {
                  this.categoryProperty().set(category);
              }
          }

          public static void main(String[] args) {
              launch(args);
          }
      }
      ---------- END SOURCE ----------

            scfitch Stephen Fitch
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: