[prev in list] [next in list] [prev in thread] [next in thread]
List: openjdk-openjfx-dev
Subject: Withdrawn: 8185887: TableRowSkinBase fails to correctly virtualize cells in horizontal direction
From: duke <duke () openjdk ! org>
Date: 2023-04-29 2:59:53
Message-ID: dI9i9bToCNnsC8rGDMTjCWAegMtZlEddtM26LUgyEfY=.cfd964e5-6040-451e-834a-15233b98174a () github ! com
[Download RAW message or body]
On Mon, 24 Feb 2020 07:39:43 GMT, yosbits <duke@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
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic