【问题标题】:JavaFX: How to remember scroll location of tabcontent after refreshing content ?JavaFX:刷新内容后如何记住标签内容的滚动位置?
【发布时间】:2017-04-25 08:41:22
【问题描述】:

我正在使用 JavaFX 中的树视图实现文件浏览器。我将 Tab 中的树视图设置为内容。当我使用预定线程刷新树视图的元素时,我无法滚动到先前选择的树项目。这是我实现的最小版本。

 /**
 *
 * @author nika
 */
public class TabTreeView extends Application implements Runnable {

private TreeItem<String> root;
private TreeView<String> tv = new TreeView<>();
private static ArrayList<NumberPair> rememberExpanded = new ArrayList<>();
private TreeItem<String> previouslySelectedTreeItem;

@Override
public void run() {
    root = new TreeItem<>("Root");
    root.setExpanded(true);
    for (int i = 0; i < 10; i++) {
        TreeItem<String> sublevel = new TreeItem<>("Level : " + i + " TS: " + System.currentTimeMillis());
        final int level = i;
        if (rememberExpanded.contains(new NumberPair(level, -9999))) {
            sublevel.setExpanded(true);
        }
        sublevel.expandedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (newValue) {
                    rememberExpanded.add(new NumberPair(level, -9999));
                } else {
                    rememberExpanded.remove(new NumberPair(level, -9999));
                }
            }
        });
        for (int j = 0; j < 5; j++) {
            TreeItem<String> subsublevel = new TreeItem<>("SubLevel : " + j + " @ " + i + " TS:" + System.currentTimeMillis());
            final int level2 = j;
            if (rememberExpanded.contains(new NumberPair(level, level2))) {
                sublevel.setExpanded(true);
            }
            subsublevel.expandedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    if (newValue) {
                        rememberExpanded.add(new NumberPair(level, level2));
                    } else {
                        rememberExpanded.remove(new NumberPair(level, level2));
                    }
                }
            });

            sublevel.getChildren().add(subsublevel);
        }
        root.getChildren().add(sublevel);
    }
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            tv.setRoot(root);
            //scroll to previously selected item
            //i know this one is wrong 1. "as it is not working", 2. "because it will only look into children of root not grandchildren".
            tv.scrollTo(root.getChildren().indexOf(previouslySelectedTreeItem));
        }
    });
}

@Override
public void start(Stage primaryStage) throws Exception {
    TabPane tabpane = new TabPane();
    tv.selectionModelProperty().addListener(new ChangeListener<MultipleSelectionModel<TreeItem<String>>>() {
        @Override
        public void changed(ObservableValue<? extends MultipleSelectionModel<TreeItem<String>>> observable, MultipleSelectionModel<TreeItem<String>> oldValue, MultipleSelectionModel<TreeItem<String>> newValue) {
            previouslySelectedTreeItem = newValue.getSelectedItem();
        }
    });
    Tab t = new Tab("Demo", tv);
    tabpane.getTabs().add(t);
    BorderPane bp = new BorderPane(tabpane);
    primaryStage.setScene(new Scene(bp));
    primaryStage.show();
    ScheduledExecutorService exc = Executors.newScheduledThreadPool(1);
    exc.scheduleAtFixedRate(this, 0, 2, TimeUnit.SECONDS);

}

public static void main(String[] args) throws Exception {
    launch(TabTreeView.class, args);

}

private class NumberPair {

    int first, second;

    public NumberPair(int first, int second) {
        this.first = first;
        this.second = second;
    }

    public int getFirst() {
        return first;
    }

    public void setFirst(int first) {
        this.first = first;
    }

    public int getSecond() {
        return second;
    }

    public void setSecond(int second) {
        this.second = second;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 37 * hash + this.first;
        hash = 37 * hash + this.second;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final NumberPair other = (NumberPair) obj;
        if (this.first != other.first) {
            return false;
        }
        if (this.second != other.second) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "NumberPair{" + "first=" + first + ", second=" + second + '}';
    }

}

}

无论如何要记住滚动标签内容或树视图的位置?这样我就可以在刷新视图后恢复滚动位置。

在这个实现中,我添加了一个NumberPair 类来记住扩展项。

【问题讨论】:

    标签: java javafx treeview


    【解决方案1】:

    可以通过 styleclass 找到 TreeView 的 ScrollBar 引用。试试这个。

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            double position[] = new double[]{0.0d};
            Optional<ScrollBar> scroll = findScrollBar(tv, Orientation.VERTICAL);
            scroll.ifPresent(s -> position[0] = s.getValue());
            tv.setRoot(root);
            scroll.ifPresent(s -> s.setValue(position[0]));
        }
    });
    
    private Optional<ScrollBar> findScrollBar(TreeView<String> from, Orientation orientation) {
        Set<Node> nodes = from.lookupAll(".scroll-bar");
        return nodes.stream()
                .filter(node -> node instanceof ScrollBar && ((ScrollBar)node).getOrientation() == orientation)
                .map(node -> ((ScrollBar)node))
                .findFirst();
    }
    

    但请注意,尝试在 TreeItem 中保留相同的项目可能是一个好方法。 TreeView 旨在保持选择扩展和滚动位置,只要您从唯一根添加和删除项目。

    【讨论】:

      猜你喜欢
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      • 2015-08-28
      相关资源
      最近更新 更多