Hi All,
Wondering if anyone has experienced the following issue and looking for any possible workarounds for it.
The problem seems to have been introduced in version 17 (version 16 seems to be working fine) and it happens with 2 TreeViews (that share the same content/root) are synchronized via their corresponding scrollbars valueProperty().bindBidirectional.
Things work fine if the scrollbar is at the very top (value = 0), as soon as you scroll down and expand or collapse any items, the content of the 2 TreeViews gets out of sync (same content will be displayed in different lines).
The issue corrects itself when scroll again up/down, selecting a different row or the application loses focus.
See small code sample below that shows the issue.
Any help would be appreciated.
Thanks,
Pablo.
package javafx.test;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TreeViewSyncScrollingSample extends Application {
private static final int CHILDREN_PER_LEVEL = 5;
private static final int NUMBER_OF_LEVELS = 3;
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
final String version = String.format("Java: %s, JavaFX: %s",
System.getProperty("java.runtime.version"), System.getProperty("javafx.version"));
stage.setTitle(version);
final Scene scene = new Scene(new Group(), 500, 400);
Group sceneRoot = (Group) scene.getRoot();
final TreeItem<String> root = createRootNode();
final TreeView<String> treeView1 = new TreeView<>(root);
// treetable 2
final TreeView<String> treeView2 = new TreeView<>(root);
// create the layout and start
final HBox hbox = new HBox(treeView1, treeView2);
sceneRoot.getChildren().add(hbox);
stage.setScene(scene);
stage.show();
final ScrollBar scrollBar1 = findVerticalScrollBar(treeView1);
final ScrollBar scrollBar2 = findVerticalScrollBar(treeView2);
scrollBar1.valueProperty().bindBidirectional(scrollBar2.valueProperty());
}
private ScrollBar findVerticalScrollBar(Parent table) {
return (ScrollBar)table.lookup(".scroll-bar:vertical");
}
private List<TreeItem<String>> createChildren(int level, String idPrefix) {
if (level == NUMBER_OF_LEVELS) {
return null;
}
final List<TreeItem<String>> thisLevelChildren = new ArrayList<>();
for (int i = 0; i < CHILDREN_PER_LEVEL; i++) {
final String id = String.format("%s%s", idPrefix, i);
final TreeItem<String> child = new TreeItem<>(String.format("Child %s", id));
final List<TreeItem<String>> nextLevelChildren = createChildren(level+1, id);
if (nextLevelChildren != null) {
child.setExpanded(true);
child.getChildren().setAll(nextLevelChildren);
}
thisLevelChildren.add(child);
}
return thisLevelChildren;
}
private TreeItem<String> createRootNode() {
final TreeItem<String> root = new TreeItem<>("Root");
final List<TreeItem<String>> childNodes = createChildren(0, "");
root.setExpanded(true);
root.getChildren().setAll(childNodes);
return root;
}
}