Skip to content

Performance issue when accessing visibleCells().get(x) #131

@PavelTurk

Description

@PavelTurk

I'm working on scrolling rows when the user presses Page Up or Page Down. If the user presses the key just once, everything works fine. But if they press and hold the key, the application starts to lag, and once it becomes responsive again, a large portion of content has already been scrolled.

To identify the cause, I created a test - click on the VirtualFlow, press and hold the Page Down key. The performance issue is related to this line:

var row = this.flow.visibleCells().get(random.nextInt(this.flow.visibleCells().size()));

If this line is commented out, everything works smoothly:

Image

Otherwise, the system starts to lag:

Image

Getting a Row instance is necessary in order to place the caret on it.

Test:

public class FlowTest extends Application {

    private static class Row implements Cell<Integer, Node> {

        private final Label label = new Label();

        private final Pane pane1 = new Pane();

        private final HBox box1 = new HBox();

        private final HBox box2 = new HBox(label);

        private final List<Text> texts = new ArrayList<>();

        private final StackPane stackPane = new StackPane(pane1, box1, box2);

        public Row(Integer index) {
            label.setText(String.valueOf(index));
            box1.setPadding(new Insets(0, 0, 0, 50));
            for (var i = 0; i < 60 ; i++) {
                var t = new Text(String.valueOf(i));
                box1.getChildren().add(t);
                this.texts.add(t);
            }
        }

        @Override
        public void updateItem(Integer item) {
            if (item == null) {
                label.setText("");
            } else {
                label.setText(String.valueOf(item));
            }
            var i = 0;
            for (var t : texts) {
                t.setText(String.valueOf(i++));
            }
        }

        @Override
        public Node getNode() {
            return stackPane;
        }

        @Override
        public boolean isReusable() {
            return true;
        }
    }

    private VirtualFlow<Integer, Row> flow;

    private ObservableList<Integer> rows;

    @Override
    public void start(Stage primaryStage) throws Exception {
        List<Integer> list = new ArrayList<>();
        for (var i = 1; i <= 100000; i++) {
            list.add(i);
        }
        rows = FXCollections.observableList(list);
        flow = VirtualFlow.createVertical(rows, r -> new Row(r));
        flow.setFocusTraversable(true);
        var random = new Random();
        flow.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
            if (e.getCode() == PAGE_DOWN) {
                flow.scrollYBy(flow.getHeight());
                Platform.runLater(() -> {
//                    var row = this.flow.visibleCells().get(random.nextInt(this.flow.visibleCells().size()));
                });
                e.consume();
            }
        });
        VirtualizedScrollPane<VirtualFlow<Integer, Row>> scrollPane = new VirtualizedScrollPane<>(flow);
        VBox.setVgrow(scrollPane, Priority.ALWAYS);
        var root = new VBox(scrollPane);
        Scene scene = new Scene(root, 1200, 900);
        primaryStage.setTitle("Flow Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions