有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Javafx,滚动窗格,线条滚动不按页面

我有一个可滚动的VBox,里面有很多文本字段。我可以从一个文本字段浏览到下一个文本字段。当我到达最后一个当前可见的页面并再次按TAB键时,滚动窗格切换到下一个“页面”,光标位于新的最上面的文本字段中

但我需要一行一行的滚动行为,同时从文本字段跳到可见区域底部的下一个字段

任何有想法的人

  package test;

  import javafx.application.Application;
  import javafx.scene.Scene;
  import javafx.scene.control.ScrollPane;
  import javafx.scene.control.TextField;
  import javafx.scene.layout.HBox;
  import javafx.scene.layout.VBox;
  import javafx.stage.Stage;

  public class Scroller extends Application {

  @Override
  public void start(Stage primaryStage) {

    VBox vb = new VBox();
    for (int i = 0; i < 360; i++) {
        TextField x = new TextField(String.valueOf(i));
        vb.getChildren().add(x);
    }
    ScrollPane sp = new ScrollPane(vb);
    sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
    sp.setFitToWidth(true);

    TextField tf = new TextField();
    HBox root = new HBox();
    root.getChildren().addAll(sp, tf);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
  }

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

共 (1) 个答案

  1. # 1 楼答案

    内容坐标中顶部的坐标可以确定为

    topY = (contentHeight - viewportHeight) * vValue
    

    可以使用此公式和场景的focusedNode属性的侦听器将聚焦节点的底部滚动到视口的底部:

    public static boolean isChild(Parent parent, Node node) {
        while (node != null && node != parent) {
            node = node.getParent();
        }
        return parent == node;
    }
    
    @Override
    public void start(Stage primaryStage) {
        VBox vb = new VBox();
        for (int i = 0; i < 360; i++) {
            TextField x = new TextField(String.valueOf(i));
            vb.getChildren().add(x);
        }
        ScrollPane sp = new ScrollPane(vb);
        sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
        sp.setFitToWidth(true);
    
        TextField tf = new TextField();
        HBox root = new HBox();
        root.getChildren().addAll(sp, tf);
    
        Scene scene = new Scene(root, 300, 250);
        scene.focusOwnerProperty().addListener((o, oldVal, newVal) -> {
            if (isChild(vb, newVal)) {
                // get bounds of focused node in ScrollPane content
                Bounds bounds = newVal.getLayoutBounds();
                while (newVal != vb) {
                    bounds = newVal.localToParent(bounds);
                    newVal = newVal.getParent();
                }
                double h = vb.getHeight();
                double vH = sp.getViewportBounds().getHeight();
    
                // scroll node to bottom of the viewport if bottom is not in view
                if (bounds.getMaxY() > sp.getVvalue() * (h - vH) + vH) {
                    sp.setVvalue((bounds.getMaxY() - vH) / (h - vH));
                }
            }
        });
    
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }