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

TableView/Row/Cell: must update cells on receiving an update event from the items

XMLWordPrintable

      The example below has a custom TableCell that wants to style itself based on data in another column (the "real" use-case is at SO https://stackoverflow.com/q/46290417/203657). It does so in its updateItem. Which must be called whenever the underlying item changed in any way - but isn't if the change is an update.

      To reproduce, run and click the checkbox in the second column
      - expected: background of first column in same row is changed
      - actual: nothing happens

      Not certain if this is a regression somehow (even if technically it can't ;) maybe introduced when virtualizing the row - because I seem to (very) vaguely remember that in earlier versions there was no problem ... mere speculation;) And didn't try yet to nail the exact location.

      The example:

      import java.util.logging.Logger;

      import de.swingempire.fx.util.FXUtils;
      import javafx.application.Application;
      import javafx.beans.Observable;
      import javafx.collections.FXCollections;
      import javafx.collections.ListChangeListener;
      import javafx.collections.ObservableList;
      import javafx.scene.Scene;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableRow;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.CheckBoxTableCell;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.scene.control.cell.TextFieldTableCell;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;
      import javafx.util.converter.DefaultStringConverter;

      /**
       * CheckBoxTableCell: update editable state of one column based of
       * the boolean in another column
       * https://stackoverflow.com/q/46290417/203657
       *
       * Bug in skins: cell not updated on listChange.wasUpdated
       */
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class TableViewUpdateBug extends Application {

          
          /**
           * TableCell that updates state based on another value in the row.
           */
          public static class DisableTextFieldTableCel extends TextFieldTableCell {
              
              public DisableTextFieldTableCel() {
                  super(new DefaultStringConverter());
              }

              /**
               * Just to see whether or not this is called on update notification
               * from the items (it's not)
               */
              @Override
              public void updateIndex(int index) {
                  super.updateIndex(index);
      // LOG.info("called? " + index);
              }
              
              /**
               * Implemented to change background based on
               * visible property of row item.
               */
              @Override
              public void updateItem(Object item, boolean empty) {
                  super.updateItem(item, empty);
                  TableRow<TableColumn> currentRow = getTableRow();
                  boolean editable = false;
                  if (!empty && currentRow != null) {
                      TableColumn column = currentRow.getItem();
                      if (column != null) {
                          editable = column.isVisible();
                      }
                  }
                  if (!empty) {
                      if (editable) {
                          this.setStyle("-fx-background-color: red");
                      } else {
                          this.setStyle("-fx-background-color: green");
                      }
                  } else {
                      setStyle("-fx-background-color: null");
                  }
              }
              
          }
          
          @Override
          public void start(Stage primaryStage) {
              // data: list of tableColumns with extractor on visible property
              ObservableList<TableColumn> data = FXCollections.observableArrayList(
                      c -> new Observable[] {c.visibleProperty()});
                      
              data.addAll(new TableColumn("first"), new TableColumn("second"));
              
              TableView<TableColumn> table = new TableView<>(data);
              table.setEditable(true);
              
              // verify that we get an update
              data.addListener((ListChangeListener) c -> {
                  while(c.next()) {
                      if (c.wasUpdated()) {
                          LOG.info("was update on " + (((TableColumn) c.getList().get(c.getFrom())).getText()));
                      }
                      //FXUtils.prettyPrint(c);
                  }
              });
              TableColumn<TableColumn, String> text = new TableColumn<>("Text");
              text.setCellFactory(c -> new DisableTextFieldTableCel()); //TextFieldTableCell.forTableColumn());
              text.setCellValueFactory(new PropertyValueFactory<>("text"));

              TableColumn<TableColumn, Boolean> visible = new TableColumn<>("Visible");
              visible.setCellValueFactory(new PropertyValueFactory<>("visible"));
              visible.setCellFactory(CheckBoxTableCell.forTableColumn(visible));
              
              table.getColumns().addAll(text, visible);
              
              BorderPane root = new BorderPane(table);
              Scene scene = new Scene(root, 300, 150);

              primaryStage.setScene(scene);
              primaryStage.show();
          }

          public static void main(String[] args) {
              launch(args);
          }
          
          @SuppressWarnings("unused")
          private static final Logger LOG = Logger
                  .getLogger(TableViewUpdateBug.class.getName());
      }

            Unassigned Unassigned
            fastegal Jeanette Winzenburg
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: