FXMisc / Flowless

Efficient VirtualFlow for JavaFX
BSD 2-Clause "Simplified" License
185 stars 38 forks source link

Scroll thumb jumps ahead and returns back #124

Open PavelTurk opened 6 days ago

PavelTurk commented 6 days ago

I need to scroll up (row by row) on key pressing. This is my code:

public class FlawTest extends Application {

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

        private Integer rowIndex;

        private final Label label = new Label();

        private final HBox hBox = new HBox(label);

        public FlowRow(Integer rowIndex) {
            this.rowIndex = rowIndex;
            label.setText(String.valueOf(rowIndex));
        }

        @Override
        public void updateItem(Integer item) {
            rowIndex = item;
            if (item == null) {
                label.setText("");
            } else {
                label.setText(String.valueOf(rowIndex));
            }
        }

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

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

    private VirtualFlow<Integer, FlowRow> flow;

    private ObservableList<Integer> rows;

    @Override
    public void start(Stage primaryStage) throws Exception {
        List<Integer> list = new ArrayList<>();
        for (var i = 0; i <= 400; i++) {
            list.add(i);
        }
        rows = FXCollections.observableList(list);
        flow = VirtualFlow.createVertical(rows, row -> new FlowRow(row));
        VirtualizedScrollPane<VirtualFlow<Integer, FlowRow>> scrollPane = new VirtualizedScrollPane<>(flow);
        VBox.setVgrow(scrollPane, Priority.ALWAYS);
        VBox root = new VBox(scrollPane);
        root.setOnKeyPressed(e -> scrollRowUp());
        Scene scene = new Scene(root, 865, 400);
        primaryStage.setTitle("Flaw Test");
        primaryStage.setScene(scene);
        primaryStage.show();
        root.requestFocus();
        flow.showAsLast(400);
    }

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

    private int rowIndex = 280;

    //Main test logic is here 
    private void scrollRowUp() {
        if (this.rowIndex == 0) {
            return;
        }
        this.rowIndex--;
        var row = flow.getCellIfVisible(rowIndex).orElse(null);// I need row instance
        if (row == null) {
            flow.showAsFirst(rowIndex);
            row = flow.getCell(rowIndex);
        } else {
            //it can be visible but not entirely
            if (flow.getFirstVisibleIndex() == rowIndex) {
                flow.showAsFirst(rowIndex);
            }
        }
    }
}

And this is the result:

https://github.com/user-attachments/assets/352f25e5-e98d-4582-8439-7b389d12e5ec

As you see at seconds 5-6 thumb jumps ahead and then returns back. In real application I see a lot of this jumping (sometimes it jumps to 0 and returns back). At the same time, I am not sure if it is a bug or something wrong with my code.

Jugen commented 3 days ago

Yeah, that's an unfortunate side effect of PR #78 sometimes ....