javajavafx

How to set items to JavaFX VirtualFlow?


I know two VirtualFlow implementations—one native to JavaFX and another from the Flowless library. I know how to use Flowless VirtuaFlow, but now, I would like to try using the JavaFX VirtualFlow. However, I don't understand how to pass an ObservableList<T> items to this VirtualFlow. Here is my code:

public class NewMain extends Application {

    public class VirtualCell<T> extends IndexedCell<T> {

    }

    private final VirtualFlow<VirtualCell<String>>  virtualFlow = new VirtualFlow<>();

    @Override
    public void start(Stage primaryStage) {
        this.virtualFlow.setCellFactory(v -> new VirtualCell<>());
        List<String> list = new ArrayList<>();
        for (var i = 0; i < 100; i++) {
            list.add("Item " + i);
        }
        ObservableList<String> items = FXCollections.observableArrayList(list);
        //this.virtualFlow.set items  ????

        var root = new VBox(this.virtualFlow);
        Scene scene = new Scene(root, 600, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

Could anyone say how to do it?


Solution

  • VirtualFlow doesn't directly accept ObservableList.

    You should extend ListCell<> to handle string directly.

    public class VirtualCell extends IndexedCell<String> {
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setText(null);
            } else {
                setText(item);
            }
        }
    
        // it gave me a missing skin error, this fixed it.
        @Override
        protected Skin<?> createDefaultSkin() {
            return new CellSkinBase<>(this);
        }
    }
    

    the VirtCell class extends IndexedCell and overrides the updateItem method to properly display the item.

    Then you need to set cell factory:

    @Override
    public void start(Stage primaryStage) {
        List<String> list = new ArrayList<>();
        for (var i = 0; i < 100; i++) {
            list.add("Item " + i);
        }
        ObservableList<String> items = FXCollections.observableArrayList(list);
    
        virtualFlow.setCellFactory(vf -> new VirtualCell());
        virtualFlow.setCellCount(items.size());
    
        virtualFlow.setCellFactory(vf -> new VirtualCell() {
            @Override
            public void updateIndex(int index) {
                super.updateIndex(index);
                if (index >= 0 && index < items.size()) {
                    updateItem(items.get(index), false);
                } else {
                    updateItem(null, true);
                }
            }
        });
    
        var root = new VBox(this.virtualFlow);
        Scene scene = new Scene(root, 600, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }