FXMisc / Flowless

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

Question: How to make VirtualFlow use existing instances of the rows instead of creating new ones #120

Closed PavelTurk closed 2 weeks ago

PavelTurk commented 2 weeks ago

This is my first experience with Flowless and this is my test 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));
            System.out.println("Row created");
        }

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

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

    }

    private VirtualFlow<Integer, FlowRow> flow;

    private ObservableList<Integer> rows = FXCollections.observableArrayList();

    @Override
    public void start(Stage primaryStage) throws Exception {

        flow = VirtualFlow.createVertical(rows, row -> new FlowRow(row));
        VirtualizedScrollPane<VirtualFlow<Integer, FlowRow>> scrollPane = new VirtualizedScrollPane<>(flow);
        VBox.setVgrow(scrollPane, Priority.ALWAYS);

        var button = new Button("Test");
        button.setOnAction(e -> {
            rows.clear();
            List<Integer> list = new ArrayList<>();
            for (var i = 0; i < 100000; i++) {
                list.add(i);
            }
            rows.addAll(list);
        });
        VBox root = new VBox(scrollPane, button);
        Scene scene = new Scene(root, 400, 300);
        primaryStage.setTitle("Flaw Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

I expect that when I make scrolling then updateItem method will be called for existing rows, however, instead of this new instances of the rows are created.

Could anyone say what I am doing wrong?

Jugen commented 2 weeks ago

FlowRow needs to override Cell isReusable with:

public boolean isReusable() {
    return true;
}
PavelTurk commented 2 weeks ago

@Jugen Yes, it helped. Thank you very much