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

TreeTableView updates invisible cells

    XMLWordPrintable

Details

    • x86_64
    • windows_10

    Description

      ADDITIONAL SYSTEM INFORMATION :
      Win 10, OpenJDK 17.0.1

      A DESCRIPTION OF THE PROBLEM :
      Hello,

      i noticed that with JFX 17 (.0.1 and .0.2, too) the contents of all cells in a TreeTableView are generated. In JFX 16 the issue did not seem to appear.

      Furthermore, i noticed that the issue only appears if there are multiple columns and the cells in those columns have different sizes.

      I prepared a minimal example: https://github.com/SteffenHeu/jfxcellbug
      I installed a logger, that will print the cell value of the updated cell, so you can see all cells are updated.
      If you change the java fx version in the build.gradle to 16, the issue won't appear.

      I traced the call stack that lead to the update in our application with java fx 16 <Attached screenshot> and 17 <>, and they are significantly different. However, i don't know if that's the original source of the issue.

      REGRESSION : Last worked in version 16

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the example project, start scrolling down a bit and then scroll up.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      updateItem only called for visible cells
      ACTUAL -
      updateItem called for all cells in the TreeTableView

      ---------- BEGIN SOURCE ----------
      package com.example.jfx17_table_cell;

      import java.io.IOException;
      import java.util.logging.Logger;
      import javafx.application.Application;
      import javafx.beans.property.SimpleLongProperty;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.TreeItem;
      import javafx.scene.control.TreeTableCell;
      import javafx.scene.control.TreeTableColumn;
      import javafx.scene.control.TreeTableView;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.FlowPane;
      import javafx.stage.Stage;
      import javafx.util.Callback;

      public class HelloApplication extends Application {

        public record Wrapper(Long value, Long value2) {

        }

        private static final Logger logger = Logger.getLogger(HelloApplication.class.getName());

        @Override
        public void start(Stage stage) throws IOException {
          BorderPane pane = new BorderPane();
          final TreeItem<Wrapper> root = new TreeItem<>(new Wrapper(0L, 0L));
          root.setExpanded(true);
          TreeTableView<Wrapper> table = new TreeTableView<>(root);
          table.setShowRoot(false);
          TreeTableColumn<Wrapper, Long> column = new TreeTableColumn<>();
          TreeTableColumn<Wrapper, Long> column2 = new TreeTableColumn<>();
          column2.setMinWidth(20);

          pane.setCenter(table);

          column.setCellFactory(new Callback<>() {
            @Override
            public TreeTableCell<Wrapper, Long> call(TreeTableColumn<Wrapper, Long> param) {
              return new TreeTableCell<>() {
                @Override
                protected void updateItem(Long item, boolean empty) {
                  super.updateItem(item, empty);
                  if (!empty) {
                    logger.info("updating " + item);
                  }
                  FlowPane graphic = new FlowPane(new Label("Graphic " + item));
      // graphic.setMinWidth(120);
                  setGraphic(graphic);
                  setMinWidth(120);
                }
              };
            }
          });

          column.setCellValueFactory(
              param -> new SimpleLongProperty(param.getValue().getValue().value).asObject());
          column2.setCellValueFactory(param -> new SimpleLongProperty(param.getValue().getValue().value2).asObject());

          for (long i = 1; i < 3_000; i++) {
            root.getChildren().add(new TreeItem<>(new Wrapper(i, i*i)));
          }

          table.getColumns().addAll(column, column2);

          Scene scene = new Scene(pane, 500, 500);
          stage.setTitle("Hello! Scroll a bit up and down and watch the log");
          stage.setScene(scene);
          stage.show();
        }

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

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

      CUSTOMER SUBMITTED WORKAROUND :
      None found

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              kpk Karthik P K
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated: