简体   繁体   English

JavaFX ScrollPane setVvalue()无法按预期工作

[英]JavaFX ScrollPane setVvalue() not working as intended

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. 在我的应用程序中,我有一个带有VBox的ScrollPane,它可能包含0到1000个窗格,每个窗格的设置高度为90。 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. 每个窗格都有相关的项目,这些项目可以从清除VBox并添加其子级的按钮内加载,并添加“返回结果”按钮,该按钮加载前一个列表,并应返回到ScrollPane中的相同位置。 However, the setVvalue() doesn't appear to be working. 但是,setVvalue()似乎不起作用。 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);
    }
}

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. setVvalue()可以工作,并在打印时将ScrollPane更改回其旧值,但是ScrollPane本身不会移到任何位置并停留在顶部。 Does it have to do with removing and adding Nodes to the VBox? 它与删除节点并将其添加到VBox是否有关? Why is the ScrollPane not moving when setting its Vvalue? 设置其Vvalue时为什么ScrollPane不移动?

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. 在您调用scroll.setVvalue(vValue) ,滚动窗格未执行布局,因为其内容已更改,因此未“重新测量”其内容的大小。 So the scroll bar "thumb" is being repositioned by interpreting the vvalue in the context of the previous layout. 因此,通过在先前布局的上下文中解释vvalue来重新定位滚动条“ thumb”。 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);
    });
}

Aside: Are these methods being called from a background thread? 除了:这些方法是否从后台线程调用? Why are their contents wrapped in a Platform.runLater(...) ? 为什么将它们的内容包装在Platform.runLater(...)

In my case calling the layout() method didn't work. 就我而言,调用layout()方法不起作用。 I also had to call applyCss() to my current scene. 我还必须对当前场景调用applyCss()

The relevant FXML: 相关的FXML:

<ScrollPane fx:id="messageScrollPane" fitToWidth="true" fitToHeight="true">
    VBox fx:id="messageBox"/>
</ScrollPane>

I wanted the scrollpane to automatically scroll down if I add a new Label to 如果要向其中添加新标签,我希望滚动窗格自动向下滚动

messageBox 

So my method to achieve this is the following: 因此,我的实现方法如下:

public void addMessage(String message) {
    messageBox.getChildren().add(new Label(message));

    currentScene.applyCss();
    currentScene.layout();

    messageScrollPane.setVvalue(1.0);
}

Hope it helps someone. 希望它可以帮助某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM