On Mon, 24 Feb 2020 07:39:43 GMT, yosbits <d...@openjdk.org> wrote:

> If there are many columns, the current TableView will stall scrolling. 
> Resolving this performance issue requires column virtualization. 
> Virtualization mode is enabled when the row height is fixed by the following 
> method.
> 
> `tableView.setFixedCellSize(height)`
> 
> This proposal includes a fix because the current code does not correctly 
> implement column virtualization.
> 
> The improvement of this proposal can be seen in the following test program.
> 
> ``` Java
> import java.util.Arrays;
> import java.util.Collections;
> 
> import javafx.animation.AnimationTimer;
> import javafx.application.Application;
> import javafx.beans.property.SimpleStringProperty;
> import javafx.collections.ObservableList;
> import javafx.scene.Scene;
> import javafx.scene.control.Button;
> import javafx.scene.control.TableColumn;
> import javafx.scene.control.TableView;
> import javafx.scene.layout.BorderPane;
> import javafx.scene.layout.HBox;
> import javafx.stage.Stage;
> 
> public class BigTableViewTest2 extends Application {
>       private static final boolean USE_WIDTH_FIXED_SIZE = false;
>       private static final boolean USE_HEIGHT_FIXED_SIZE = true;
> //    private static final int COL_COUNT=30;
> //    private static final int COL_COUNT=300;
> //    private static final int COL_COUNT=600;
>       private static final int COL_COUNT = 1000;
>       private static final int ROW_COUNT = 1000;
> 
>       @Override
>       public void start(final Stage primaryStage) throws Exception {
>               final TableView<String[]> tableView = new TableView<>();
> 
> //        tableView.setTableMenuButtonVisible(true); //too heavy
>               if (USE_HEIGHT_FIXED_SIZE) {
>                       tableView.setFixedCellSize(24);
>               }
> 
>               final ObservableList<TableColumn<String[], ?>> columns = 
> tableView.getColumns();
>               for (int i = 0; i < COL_COUNT; i++) {
>                       final TableColumn<String[], String> column = new 
> TableColumn<>("Col" + i);
>                       final int colIndex = i;
>                       column.setCellValueFactory((cell) -> new 
> SimpleStringProperty(cell.getValue()[colIndex]));
>                       columns.add(column);
>                       if (USE_WIDTH_FIXED_SIZE) {
>                               column.setPrefWidth(60);
>                               column.setMaxWidth(60);
>                               column.setMinWidth(60);
>                       }
>               }
> 
>               final Button load = new Button("load");
>               load.setOnAction(e -> {
>                       final ObservableList<String[]> items = 
> tableView.getItems();
>                       items.clear();
>                       for (int i = 0; i < ROW_COUNT; i++) {
>                               final String[] rec = new String[COL_COUNT];
>                               for (int j = 0; j < rec.length; j++) {
>                                       rec[j] = i + ":" + j;
>                               }
>                               items.add(rec);
>                       }
>               });
> 
>               final Button reverse = new Button("reverse columns");
>               reverse.setOnAction(e -> {
>                       final TableColumn<String[], ?>[] itemsArray = 
> columns.toArray(new TableColumn[0]);
>                       Collections.reverse(Arrays.asList(itemsArray));
>                       tableView.getColumns().clear();
>                       
> tableView.getColumns().addAll(Arrays.asList(itemsArray));
>               });
> 
>               final Button hide = new Button("hide % 10");
>               hide.setOnAction(e -> {
>                       for (int i = 0, n = columns.size(); i < n; i++) {
>                               if (i % 10 == 0) {
>                                       columns.get(i).setVisible(false);
>                               }
>                       }
>               });
> 
>               final BorderPane root = new BorderPane(tableView);
>               root.setTop(new HBox(8, load, reverse, hide));
> 
>               final Scene scene = new Scene(root, 800, 800);
>               primaryStage.setScene(scene);
>               primaryStage.show();
>               this.prepareTimeline(scene);
>       }
> 
>       public static void main(final String[] args) {
>               Application.launch(args);
>       }
> 
>       private void prepareTimeline(final Scene scene) {
>               new AnimationTimer() {
>                       @Override
>                       public void handle(final long now) {
>                               final double fps = 
> com.sun.javafx.perf.PerformanceTracker.getSceneTracker(scene).getInstantFPS();
>                               ((Stage) scene.getWindow()).setTitle("FPS:" + 
> (int) fps);
>                       }
>               }.start();
>       }
> }
> 
> 
> ``` Java
> import javafx.animation.AnimationTimer;
> import javafx.application.Application;
> import javafx.application.Platform;
> import javafx.beans.property.ReadOnlyStringWrapper;
> import javafx.scene.Scene;
> import javafx.scene.control.TreeItem;
> import javafx.scene.control.TreeTableColumn;
> import javafx.scene.control.TreeTableColumn.CellDataFeatures;
> import javafx.scene.control.TreeTableView;
> import javafx.stage.Stage;
> 
> public class BigTreeTableViewTest extends Application {
> 
>       private static final boolean USE_HEIGHT_FIXED_SIZE = true;
> //    private static final int COL_COUNT = 900;
>       private static final int COL_COUNT = 800;
> //    private static final int COL_COUNT = 600;
> //    private static final int COL_COUNT = 500;
> //    private static final int COL_COUNT = 400;
> //    private static final int COL_COUNT = 300;
> //    private static final int COL_COUNT = 200;
> //    private static final int COL_COUNT = 100;
> 
>       public static void main(final String[] args) {
>               Application.launch(args);
>       }
> 
>       @Override
>       public void start(final Stage stage) {
>               final TreeItem<String> root = new TreeItem<>("Root");
>               final TreeTableView<String> treeTableView = new 
> TreeTableView<>(root);
>               if (USE_HEIGHT_FIXED_SIZE) {
>                       treeTableView.setFixedCellSize(24);
>               }
>               treeTableView.setPrefWidth(800);
>               treeTableView.setPrefHeight(500);
>               stage.setWidth(800);
>               stage.setHeight(500);
> 
>               Platform.runLater(() -> {
>                       for (int i = 0; i < 100; i++) {
>                               TreeItem<String> child = this.addNodes(root);
>                               child = this.addNodes(child);
>                               child = this.addNodes(child);
>                               child = this.addNodes(child);
>                       }
>               });
> 
>               final TreeTableColumn<String, String>[] cols = new 
> TreeTableColumn[COL_COUNT + 1];
>               final TreeTableColumn<String, String> column = new 
> TreeTableColumn<>("Column");
>               column.setPrefWidth(150);
>               column.setCellValueFactory(
>                               (final CellDataFeatures<String, String> p) -> 
> new ReadOnlyStringWrapper(p.getValue().getValue()));
>               cols[0] = column;
> 
>               for (int i = 0; i < COL_COUNT; i++) {
>                       final TreeTableColumn<String, String> col = new 
> TreeTableColumn<>(Integer.toString(i));
>                       col.setPrefWidth(60);
>                       col.setCellValueFactory(val -> new 
> ReadOnlyStringWrapper(val.getValue().getValue()+":"+val.getTreeTableColumn().getText()));
>                       cols[i + 1] = col;
>               }
>               treeTableView.getColumns().addAll(cols);
> 
>               final Scene scene = new Scene(treeTableView, 800, 500);
>               stage.setScene(scene);
>               stage.show();
>               this.prepareTimeline(scene);
>       }
> 
>       private TreeItem<String> addNodes(final TreeItem<String> parent) {
> 
>               final TreeItem<String>[] childNodes = new TreeItem[20];
>               for (int i = 0; i < childNodes.length; i++) {
>                       childNodes[i] = new TreeItem<>("N" + i);
>               }
>               final TreeItem<String> root = new TreeItem<>("dir");
>               root.setExpanded(true);
>               root.getChildren().addAll(childNodes);
>               parent.setExpanded(true);
>               parent.getChildren().add(root);
>               return root;
>       }
> 
>       private void prepareTimeline(final Scene scene) {
>               new AnimationTimer() {
>                       @Override
>                       public void handle(final long now) {
>                               final double fps = 
> com.sun.javafx.perf.PerformanceTracker.getSceneTracker(scene).getInstantFPS();
>                               ((Stage) scene.getWindow()).setTitle("FPS:" + 
> (int) fps);
>                       }
>               }.start();
>       }
> 
> }

This pull request has been closed without being integrated.

-------------

PR: https://git.openjdk.org/jfx/pull/125

Reply via email to