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

Headers and cells lose alignment if columns and items are temporarily removed

XMLWordPrintable

    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      JDK-Version: 11.0.8
      JavaFX-SDK-Version: 15.0.1

      A DESCRIPTION OF THE PROBLEM :
      If you scroll to the (horizontal) end of a TableView and then temporarily remove some of the last columns and all items, the headers and cells will lose alignment after the columns and items are added again. It seems that the problem only occurs, if the table is rendered in the temporary state. The alignment is corrected after the next scoll.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run the provided test case.
      2. Press the button "Execute Test-Case"

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Headers and cells are aligned properly.
      ACTUAL -
      Headers and cells lose alignment.

      ---------- BEGIN SOURCE ----------

      import java.util.ArrayList;
      import java.util.List;
      import java.util.concurrent.Executors;

      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.collections.FXCollections;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.ProgressBar;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.ToolBar;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;

      public class TestApp extends
                           Application {

      private static final int ITEM_COUNT = 100;
      private static final int COLUMN_COUNT = 100;
      private static final int TAIL_LENGTH = 10;

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

      @Override
      public void start(Stage stage) {

      TableView<String> table = new TableView<>();
      table.getColumns().setAll(createColumns());
      table.setItems(FXCollections.observableArrayList());
      table.getItems().addAll(createItems());

      ProgressBar progressBar = new ProgressBar();
      progressBar.setVisible(false);

      Button buttonExecuteTestCase = new Button("Execute Test-Case");
      buttonExecuteTestCase.setOnAction(event -> {
      buttonExecuteTestCase.setDisable(true);
      progressBar.setVisible(true);

      table.scrollToColumnIndex(table.getColumns().size()
      - 1);

      toggleTailColumns(table);
      toggleItems(table);

      Executors.newSingleThreadExecutor().execute(() -> {
      // Ensure that there is at least one pulse in between.
      sleep();
      Platform.runLater(() -> {
      toggleTailColumns(table);
      toggleItems(table);

      buttonExecuteTestCase.setDisable(false);
      progressBar.setVisible(false);
      });
      });
      });

      ToolBar toolbar = new ToolBar(buttonExecuteTestCase,
      progressBar);

      BorderPane root = new BorderPane();
      root.setTop(toolbar);
      root.setCenter(table);

      stage.setTitle("Hello World!");
      stage.setScene(new Scene(root,
      800,
      500));
      stage.show();
      }

      private static List<TableColumn<String, ?>> createColumns() {
      List<TableColumn<String, ?>> columns = new ArrayList<>(COLUMN_COUNT);
      for (int i = 1; i <= COLUMN_COUNT; i++) {
      String name = "C"
      + i;
      TableColumn<String, String> column = new TableColumn<>(name);
      column.setCellValueFactory(cellDataFeatrues -> new SimpleStringProperty(name
      + " "
      + cellDataFeatrues.getValue()));

      columns.add(column);
      }
      return columns;
      }

      private static List<String> createItems() {
      List<String> items = new ArrayList<>(ITEM_COUNT);
      for (int i = 1; i <= ITEM_COUNT; i++) {
      items.add("R"
      + i);
      }
      return items;
      }

      private void toggleTailColumns(TableView<String> table) {
      // Temporary store for the columns, while they're not attached to the table.
      List<TableColumn<String, ?>> tail = (List<TableColumn<String, ?>>) table.getProperties().computeIfAbsent("column-tail",
      key -> new ArrayList<>(TAIL_LENGTH));
      if (tail.isEmpty()) {
      int from = table.getColumns().size()
      - TAIL_LENGTH;
      int to = table.getColumns().size();
      tail.addAll(table.getColumns().subList(from,
      to));
      table.getColumns().remove(from,
      to);
      } else {
      table.getColumns().addAll(tail);
      tail.clear();
      }
      }

      private void toggleItems(TableView<String> table) {
      if (table.getItems().isEmpty()) {
      table.getItems().addAll(createItems());
      } else {
      table.getItems().clear();
      }
      }

      private static void sleep() {
      try {
      Thread.sleep(1000);
      } catch (InterruptedException exception) {
      Thread.currentThread().interrupt();
      }
      }

      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Simulate a scroll event after the item list has been cleared and refilled.

      FREQUENCY : always


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

              Created:
              Updated: