RFR: 8185886: Improve scrolling performance of TableView and TreeTableView

Martin Polakovic github.com+5527071+sghpjuikit at openjdk.java.net
Fri Apr 3 10:58:02 UTC 2020


On Mon, 24 Feb 2020 07:39:43 GMT, yosbits <github.com+7517141+yososs at 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 javafx.animation.AnimationTimer;
> import javafx.application.Application;
> import javafx.beans.property.SimpleStringProperty;
> import javafx.collections.ObservableList;
> import javafx.scene.Scene;
> import javafx.scene.control.TableColumn;
> import javafx.scene.control.TableView;
> import javafx.scene.layout.BorderPane;
> import javafx.stage.Stage;
> 
> public class BigTableViewTest2 extends Application {
> 
> 	private static final boolean USE_WIDTH_FIXED_SIZE = true;
> 	private static final boolean USE_HEIGHT_FIXED_SIZE = true;
> //	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(Stage primaryStage) throws Exception {
> 	    final TableView<String[]> tableView = new TableView<>();
> 
> 	    final ObservableList<TableColumn<String[], ?>> columns = tableView.getColumns();
>     	for(int i=0; i<COL_COUNT; i++) {
>     		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);
> 			}
>     	}
>     
>     	ObservableList<String[]> items = tableView.getItems();
>     	for(int i=0; i<ROW_COUNT; i++) {
>     		String[] rec = new String[COL_COUNT];
>     		for(int j=0; j<rec.length; j++) {
>     			rec[j] = i+":"+j;
>     		}
>         	items.add(rec);
>     	}
> 		BorderPane root = new BorderPane(tableView);
> 		if(USE_HEIGHT_FIXED_SIZE) {
> 			tableView.setFixedCellSize(24);
> 		}
> 
>     	Scene scene = new Scene(root, 800, 800);
>     	primaryStage.setScene(scene);
>     	primaryStage.show();
>     	prepareTimeline(scene);
>     
> 	}
> 
> 	public static void main(String[] args) {
> 		Application.launch(args);
> 	}
> 
>     private void prepareTimeline(Scene scene) {
>         new AnimationTimer() {
>             @Override public void handle(long now) {
>                 double fps =  com.sun.javafx.perf.PerformanceTracker.getSceneTracker(scene).getInstantFPS();
>                 ((Stage)scene.getWindow()).setTitle("FPS:"+(int)fps);
>             }
>         }.start();
>     }
> 
> }

I took the liberty of pointing out some formatting errors

modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java line 492:

> 491:                 tableCell.requestLayout();
> 492:             }else if(fixedCellSizeEnabled && lastVisibleColumnIndex<column){
> 493:                 break;

`}else` formatting

modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java line 387:

> 386:                     }
> 387:                 }else{
> 388:                     // we only add/remove to the scenegraph if the fixed cell

`}else` formatting

modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java line 373:

> 372:                 lastVisibleColumnIndex = column;
> 373:             }else if( firstVisibleColumnIndex != -1 ) {
> 374:                 break;

`}else` formatting

modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java line 347:

> 346:         final Insets padding = getSkinnable().getPadding();
> 347:         final double vfWidth = virtualFlow == null ? 0.0:virtualFlow.getWidth();
> 348:         final double headerWidth = vfWidth - (padding.getLeft() + padding.getRight());

`0.0:` formatting

modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java line 414:

> 413:             width = snapSizeX(tableColumn.getWidth());
> 414:             if (isVisible || isOverlap(tableCell.getLayoutX(), tableCell.getLayoutX()+width, scrollX, headerWidth
> + scrollX)) { 415:                 // if the style origin is null then the property has not been

`)+w` formatting

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

PR: https://git.openjdk.java.net/jfx/pull/125


More information about the openjfx-dev mailing list