当前位置: 首页 > 知识库问答 >
问题:

JavaFX ScrollPane setVvalue()未按预期工作

魏勇军
2023-03-14

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

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有关?为什么设置滚动窗格的vValue时滚动窗格没有移动?

共有1个答案

常翰
2023-03-14

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

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

        scroll.layout();

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

旁白:这些方法是从后台线程调用的吗?为什么它们的内容包装在平台.runlater(...)中?

 类似资料:
  • 我正在使用spring Roo并希望访问Controller类中的一个bean,该类在ApplicationContext.xml中具有以下配置: 配置类本身是: 在我的Controller中,我认为一个简单的Autowired注释应该可以完成这项工作 在启动过程中,spring在setSkipWeeks方法中打印消息。不幸的是,每当我在控制器中调用config.getSkipWeeks()时,它

  • 当我运行以下程序时,它只打印 然而,从Java 8的equalsIgnoreCase文档中我们发现: 如果以下至少一项为真,则两个字符c1和c2被视为相同的忽略情况: •对每个字符应用java.lang.character.ToUpperCase(char)方法会产生相同的结果 所以我的问题是为什么这个程序不打印 在这两种操作中,都使用了大写字符。

  • 我试图使用来传输我根据前面的问题设置的自定义标头。 我在文件中读到... 我的属性包括:

  • 我正在和selenium一起工作,刮一些数据。 有一个按钮在页面上,我正在点击说“Custom_Cols”。这个按钮为我打开了一个窗口,我可以在那里选择我的列。 我的问题是为什么新窗口上的元素不可见,即使我正在等待元素的可见。补充一下,我已经尝试增加延迟时间,但我还是会偶尔出现这个错误。 我的密码在这里

  • 我正在使用Grails 2.0.1中的springsecurity插件。我的角色层次结构和其他s2属性如下所示。

  • 我有一个问题jsPlumb的deleteEndpoint函数。 我想删除没有任何连接的endpoint。我希望在“连接”时触发此操作,但我认为可能存在一些问题。 但是我把代码移到了“dblclick”,我发现了同样的问题。标记为删除的一个节点被删除,但随后系统中的每个endpoint都被冻结在原地——一旦其元素被拖动,就与该元素断开连接。我不确定是什么原因造成的:以下是相关代码和一些屏幕截图。。。

  • 我知道我做错了什么。但我找不到这里有什么问题。请帮助我正确理解这一点。