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

Calling refresh() for all virtualized controls recreates all cells instead of refreshing the cells

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • None
    • javafx
    • None
    • generic
    • generic

      When calling refresh() on virtualized Controls (ListView, TreeView, TableView, TreeTableView), all cells will be recreated completely, instead of just refreshing them.

      This is because recreateCells() of the VirtualFlow is called when refresh() was called. This is not needed, since refreshing the cells can be done much cheaper with rebuildCells().

      This will reset all cells (index = -1), add them to the pile and fill them back in the viewport with an index again. This ensures updateItem() is called.

      The contract of refresh() is also a big vague, stating:
      Calling {@code refresh()} forces the XXX control to recreate and repopulate the cells necessary to populate the visual bounds of the control.
      In other words, this forces the XXX to update what it is showing to the user. This is useful in cases where the underlying data source has changed in a way that is not observed by the XXX itself.

      As written above, recreating is not needed in order to fulfull the contract of updating what is shown to the user in case the underlying data source changed without JavaFX noticing (e.g. calling a normal Setter without any Property and therefore listener involved).

      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.collections.FXCollections;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableRow;
      import javafx.scene.control.TableView;
      import javafx.scene.layout.Priority;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      public class TableRefresh extends Application {

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

          @Override
          public void start(Stage stage) throws Exception {
              TableView<String> tv = new TableView<>();
              tv.setEditable(true);
              tv.setRowFactory(e -> {
                  System.out.println("Creating row");
                  return new TableRow<>();
              });
              TableColumn<String, String> col = new TableColumn<>("Name");
              col.setCellValueFactory(i -> new SimpleStringProperty(i.getValue()));

              tv.getColumns().addAll(col);

              tv.setItems(FXCollections.observableArrayList("A", "B"));
              VBox.setVgrow(tv, Priority.ALWAYS);
              Button btn = new Button("Refresh");
              btn.setOnAction(e -> tv.refresh());
              Scene scene = new Scene(new VBox(tv, btn));

              stage.setScene(scene);
              stage.setTitle("Table Refresh");
              stage.show();
          }

      }

            mhanl Marius Hanl
            mhanl Marius Hanl
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: