JavaFX ScrollPane setVvalue()无法按预期工作 [英] JavaFX ScrollPane setVvalue() not working as intended

查看:136
本文介绍了JavaFX ScrollPane setVvalue()无法按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我有一个带有VBox的ScrollPane,它可能包含0到1000个窗格,每个窗格的设置高度为90.每个窗格都有相关的项目,这些项目可以从清除VBox并添加其子级的按钮内加载,并带有返回结果"按钮,该按钮可以加载上一个列表,并应返回到ScrollPane中的相同位置.但是,setVvalue()似乎不起作用.窗格及其子项属于同一类.

In my application I have a ScrollPane with a VBox that potentially contains anywhere from 0 to 1000 panes at a set height of 90 each. Each pane has related items that could loaded from a button inside that clears the VBox and adds its children along with a 'Return to Results' button that loads the previous list and should return to the same place in the ScrollPane. However, the setVvalue() doesn't appear to be working. The panes and their children are of the same class.

package application;

import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;


public class Main extends Application {

    public VBox resultsBox;
    public ScrollPane scroll;
    public List<CustomClass> results = new ArrayList<CustomClass>();
    public Button returnToResults;

    public class CustomClass extends HBox {
        public List<CustomClass> items;

        public boolean hasItems() {
            return items != null && !items.isEmpty();
        }

        public CustomClass(String text, boolean hasItems) {
            setMinHeight(90);
            setPrefHeight(90);
            setMaxHeight(90);
            setMaxWidth(Double.MAX_VALUE);
            setAlignment(Pos.CENTER);
            setStyle("-fx-border-color: red");

            Button children = new Button("View Children "+text);
            children.setDisable(!hasItems);
            getChildren().add(children);
            children.setOnAction(e -> {
                viewChildren(this);
            });

            if(hasItems) {
                items = new ArrayList<CustomClass>();
                for(int i=0; i<10; i++) {
                    items.add(new CustomClass(text+"."+i, false));
                }
            }
        }
    }

    public double vValue = 0.0;

    public void viewChildren(CustomClass cc) {
        Platform.runLater(() -> {
            vValue = scroll.getVvalue();
            System.out.println("0. "+vValue);
            resultsBox.getChildren().clear();
            resultsBox.getChildren().addAll(cc.items);
            returnToResults.setDisable(false);
        });
    }

    public void returnToResults() {
        Platform.runLater(() -> {
            resultsBox.getChildren().clear();
            resultsBox.getChildren().addAll(results);
            System.out.println("1. "+vValue+"    "+scroll.getVvalue());
            scroll.setVvalue(vValue);
            System.out.println("2. "+vValue+" -> "+scroll.getVvalue()); // Sets correctly.
            returnToResults.setDisable(true);
        });
    }

    public void start(Stage stage) throws Exception {

        resultsBox = new VBox(5);
        resultsBox.setFillWidth(true);
        resultsBox.setAlignment(Pos.TOP_CENTER);

        scroll = new ScrollPane(resultsBox);
        scroll.setMaxWidth(Double.MAX_VALUE);
        scroll.setFitToWidth(true);

        for(int i=0; i<100; i++) {
            results.add(new CustomClass("#"+i, true));
        }

        resultsBox.getChildren().addAll(results);

        returnToResults = new Button("Return to Results");
        returnToResults.setStyle("-fx-base: green");
        returnToResults.setDisable(true);
        returnToResults.setOnAction(e -> {
            returnToResults();
        });

        BorderPane root = new BorderPane();
        root.setCenter(scroll);
        root.setBottom(returnToResults);

        Scene scene = new Scene(root,400,400);
        stage.setScene(scene);
        stage.show();
    }

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

setVvalue()可以工作并在打印时将ScrollPane更改回其旧值,但ScrollPane本身不会移到任何位置并停留在顶部.它与删除节点并将其添加到VBox有关吗?为什么在设置ScrollPane的Vvalue时不移动?

The setVvalue() works and changes the ScrollPane back to its old value when printing it out but the ScrollPane itself does not go anywhere and stays at the top. Does it have to do with removing and adding Nodes to the VBox? Why is the ScrollPane not moving when setting its Vvalue?

推荐答案

在您调用scroll.setVvalue(vValue)时,滚动窗格未执行布局,因为其内容已更改,因此未重新测量"其内容的大小.因此,通过在先前布局的上下文中解释vvalue来重新定位滚动条"thumb".您可以使用

At the time you call scroll.setVvalue(vValue), the scroll pane hasn't performed the layout since its content has changed, and consequently hasn't "remeasured" the size of its content. So the scroll bar "thumb" is being repositioned by interpreting the vvalue in the context of the previous layout. You can fix this with

public void returnToResults() {
    Platform.runLater(() -> {
        vbox.getChildren.clear();
        vbox.getChildren.addAll(results);

        scroll.layout();

        scroll.setVvalue(vValue); 
        returnToResults.setDisable(true);
    });
}

此外:是否从后台线程调用这些方法?为什么将它们的内容包装在Platform.runLater(...)中?

Aside: Are these methods being called from a background thread? Why are their contents wrapped in a Platform.runLater(...)?

这篇关于JavaFX ScrollPane setVvalue()无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆