我想保存TreeView组件的当前滚动状态并随时恢复该状态。
我尝试了很多东西来获得滚动位置并将其设置回来,但无法以任何方式完成。
这里的关键点是我们需要保存min,max,value,unitInc,blockInc值并在需要时恢复这些值。只有值或仅最小值和最大值不足以正确恢复。
更新
聆听垂直值更改并存储滚动状态
Set<Node> nodes = this.treeView.lookupAll(".scroll-bar");
for (Node node : nodes) {
ScrollBar scrollBar = getScrollBar(node);
if (scrollBar.getOrientation() == Orientation.VERTICAL) {
scrollBar.valueProperty().addListener((observable, oldValue, newValue) -> {
double value = newValue.doubleValue();
if (value > 0) {
scrollState.setMin(scrollBar.getMin());
scrollState.setMax(scrollBar.getMax());
scrollState.setUnitIncrement(scrollBar.getUnitIncrement());
scrollState.setBlockIncrement(scrollBar.getBlockIncrement());
scrollState.setVerticalValue(value);
}
});
}
}
此处还存储滚动状态
private ScrollBar getScrollBar(Node node) {
ScrollBar scrollBar = (ScrollBar) node;
if (Objects.nonNull(scrollBar)) {
scrollState.setMin(scrollBar.getMin());
scrollState.setMax(scrollBar.getMax());
scrollState.setUnitIncrement(scrollBar.getUnitIncrement());
scrollState.setBlockIncrement(scrollBar.getBlockIncrement());
}
return scrollBar;
}
恢复存储的滚动状态
threadService.schedule(() -> { // run after some ms, it is important
threadService.runActionLater(() -> { // run in ui thread
Set<Node> nodes = this.treeView.lookupAll(".scroll-bar");
for (Node node : nodes) {
ScrollBar scrollBar = getScrollBar(node);
if (scrollBar.getOrientation() == Orientation.VERTICAL) {
double verticalValue = scrollState.getVerticalValue();
if (verticalValue > 0) {
scrollBar.setMin(scrollState.getMin());
scrollBar.setMax(scrollState.getMax());
scrollBar.setUnitIncrement(scrollState.getUnitIncrement());
scrollBar.setBlockIncrement(scrollState.getBlockIncrement());
scrollBar.setValue(verticalValue);
}
}
}
}, true);
}, 50, TimeUnit.MILLISECONDS);
答案 0 :(得分:2)
如果您只想在TreeView
中滚动到索引,那么您可以使用scrollTo方法(例如,您保存所选索引,然后您滚动到这个指数后来):
tree.scrollTo(5);
如果您确实希望存储然后恢复ScrollBar
的位置,则可以使用Node
类的lookupAll方法要查找.scroll-bar
样式,然后将其设置为ScrollBar
对象,该对象具有要存储的minProperty,maxProperty和valueProperty。
更新:
根据OP的发现,ScrollBar
的{{3}}和unitIncrementProperty也应该存储和恢复,以便正确支持该操作。
示例强>
在示例中,我填充了TreeView
一些虚拟数据。它包含一个Button
,用于将水平位置和垂直ScrollBar
保存到成员对象中,该成员对象可以存储位置的min,max,value,blockIncrement和unitIncrement值。它还有一个Button
来恢复上次保存的滚动条位置。
public class TreeViewSample extends Application {
// Members to store the horizontal and vertical positions
private ScrollBarState hScrollBarState = null;
private ScrollBarState vScrollBarState = null;
TreeView<String> tree;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Tree View Sample with scrollbars");
TreeItem<String> rootItem = new TreeItem<String>("Items");
rootItem.setExpanded(true);
for (int i = 1; i < 30; i++) {
TreeItem<String> item = new TreeItem<String>("Long long long long long long long Item" + i);
rootItem.getChildren().add(item);
}
tree = new TreeView<String>(rootItem);
VBox root = new VBox();
Button buttonSave = new Button("Save ScrollBars!");
buttonSave.setOnAction((event) -> {
// On save get the scrollbars and update the members (if the scrollbar is present)
ScrollBar bar = getScrollBar(tree, Orientation.HORIZONTAL);
if (bar != null)
hScrollBarState = new ScrollBarState(bar.getMin(), bar.getMax(), bar.getValue(), bar.getBlockIncrement(), bar.getUnitIncrement());
bar = getScrollBar(tree, Orientation.VERTICAL);
if (bar != null)
vScrollBarState = new ScrollBarState(bar.getMin(), bar.getMax(), bar.getValue(), bar.getBlockIncrement(), bar.getUnitIncrement());
});
Button buttonRestore = new Button("Restore ScrollBars!");
buttonRestore.setOnAction((event) -> {
restoreScrollBarPositions(getScrollBar(tree, Orientation.HORIZONTAL), hScrollBarState);
restoreScrollBarPositions(getScrollBar(tree, Orientation.VERTICAL), vScrollBarState);
});
root.getChildren().addAll(tree, buttonSave, buttonRestore);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
private ScrollBar getScrollBar(TreeView<?> tree, Orientation orientation) {
// Get the ScrollBar with the given Orientation using lookupAll
for (Node n : tree.lookupAll(".scroll-bar")) {
if (n instanceof ScrollBar) {
ScrollBar bar = (ScrollBar) n;
if (bar.getOrientation().equals(orientation))
return bar;
}
}
return null;
}
private void restoreScrollBarPositions(ScrollBar bar, ScrollBarState state) {
// Set back the position values if they present
if (bar != null && state != null) {
bar.setMin(state.min);
bar.setMax(state.max);
bar.setValue(state.value);
bar.setUnitIncrement(state.unitIncrement);
bar.setBlockIncrement(state.blockIncrement);
}
}
// Simple class to store the position values
class ScrollBarState {
double min;
double max;
double value;
double blockIncrement;
double unitIncrement;
ScrollBarState(double min, double max, double value, double blockInc, double unitInc) {
this.min = min;
this.max = max;
this.value = value;
this.blockIncrement = blockInc;
this.unitIncrement = unitInc;
}
}
}
答案 1 :(得分:0)
这可能对某人有用。我基于DVarga的解决方案创建了一个友好的状态对象。这是使用TextArea。
public class ScrollBarState
{
private final TextArea textArea;
private final Orientation orientation;
private ScrollBar scrollBar;
private double min;
private double max;
private double value;
private double blockIncrement;
private double unitIncrement;
// ---------------------------------------------------------------------------------//
// constructor
// ---------------------------------------------------------------------------------//
public ScrollBarState (TextArea textArea, Orientation orientation)
{
this.textArea = textArea;
this.orientation = orientation;
}
// ---------------------------------------------------------------------------------//
// reset
// ---------------------------------------------------------------------------------//
public void reset ()
{
scrollBar = null;
}
// ---------------------------------------------------------------------------------//
// save
// ---------------------------------------------------------------------------------//
public void save ()
{
if (scrollBar == null && !setScrollBar ())
return;
this.min = scrollBar.getMin ();
this.max = scrollBar.getMax ();
this.value = scrollBar.getValue ();
this.blockIncrement = scrollBar.getBlockIncrement ();
this.unitIncrement = scrollBar.getUnitIncrement ();
}
// ---------------------------------------------------------------------------------//
// restore
// ---------------------------------------------------------------------------------//
public void restore ()
{
if (scrollBar == null)
return;
scrollBar.setMin (min);
scrollBar.setMax (max);
scrollBar.setValue (value);
scrollBar.setUnitIncrement (unitIncrement);
scrollBar.setBlockIncrement (blockIncrement);
}
// ---------------------------------------------------------------------------------//
// setScrollBar
// ---------------------------------------------------------------------------------//
private boolean setScrollBar ()
{
for (Node node : textArea.lookupAll (".scroll-bar"))
if (node instanceof ScrollBar
&& ((ScrollBar) node).getOrientation ().equals (orientation))
{
scrollBar = (ScrollBar) node;
return true;
}
return false;
}
}