Get a list of all TreeCell objects that currently exist in a TreeView

558 views Asked by At

I know that TreeCell objects are generated dynamically by the TreeView using a cell factory.

Is there a way to get a list of all TreeCell objects that currently exist?

I suppose I could keep track of them by modifying the cell factory. As in, whenever I create a new cell add it to some list. But then I'm not sure how to remove cells from my list once the TreeView disposes them (because they went out of view).

2

There are 2 answers

1
spilot On

My solution to this is to use weak references:

[A] weak reference is a reference that does not protect the referenced object from collection by a garbage collector[.]

So, add this to your controller:

private final Set<MyTreeCell> myTreeCells = Collections.newSetFromMap(new WeakHashMap<>());

And make your CellFactory look like this:

myTreeView.setCellFactory((treeItem) -> {
        MyTreeCell c = new MyTreeCell(icf);
        Platform.runLater(() -> myTreeCells.add(c));
        return c;
    });

Now, myTreeCells will always contain the currently existing TreeCells.

Update

There is another, quite ugly solution using reflection to get a List of TreeCells. Note that this List is – as far as I know – a snapshot of JavaFXs List of TreeCells at one point in time. It is not backed.

@SuppressWarnings({ "unchecked" })
private Set<MyTreeCell> getListOfTreeCells() {
    try {
        final Field f = VirtualContainerBase.class.getDeclaredField("flow");
        f.setAccessible(true);
        final Field g = VirtualFlow.class.getDeclaredField("cells");
        g.setAccessible(true);
        final Set<MyTreeCell> s = new HashSet<>();
        s.addAll((ArrayLinkedList<MyTreeCell>) g
                .get((f.get((myTreeView.skinProperty().get())))));
        return s;
    }
    catch (NoSuchFieldException | SecurityException | IllegalArgumentException
            | IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
1
Jason Garrett On
treeView.lookupAll(".tree-cell");

This will return a Set of Nodes that can be cast to TreeCells.