【问题标题】:How to scroll to make a Node within the content of a ScrollPane visible?如何滚动以使 ScrollPane 内容中的节点可见?
【发布时间】:2012-10-02 00:02:07
【问题描述】:

鉴于带有一些子节点的巨大AnchorPaneScrollPane 的内容,我如何滚动以使当前视口之外的子节点之一可见?

【问题讨论】:

    标签: javafx-2


    【解决方案1】:

    编辑:下一个示例中的代码比我的更精确:https://stackoverflow.com/a/23518314/1054140

    你需要在content中找到这个内部节点的坐标,并相应地调整ScrollPanevValuehValue

    在下一个小应用中查看ensureVisible()方法:

    public class ScrollPaneEnsureVisible extends Application {
    
        private static final Random random = new Random();
    
        private static void ensureVisible(ScrollPane pane, Node node) {
            double width = pane.getContent().getBoundsInLocal().getWidth();
            double height = pane.getContent().getBoundsInLocal().getHeight();
    
            double x = node.getBoundsInParent().getMaxX();
            double y = node.getBoundsInParent().getMaxY();
    
            // scrolling values range from 0 to 1
            pane.setVvalue(y/height);
            pane.setHvalue(x/width);
    
            // just for usability
            node.requestFocus();
        }
    
        @Override
        public void start(Stage primaryStage) {
    
            final ScrollPane root = new ScrollPane();
            final Pane content = new Pane();
            root.setContent(content);
    
            // put 10 buttons at random places with same handler
            final EventHandler<ActionEvent> handler = new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    int index = random.nextInt(10);
                    System.out.println("Moving to button " + index);
                    ensureVisible(root, content.getChildren().get(index));
                }
            };
    
            for (int i = 0; i < 10; i++) {
                Button btn = new Button("next " + i);
                btn.setOnAction(handler);
                content.getChildren().add(btn);
                btn.relocate(2000 * random.nextDouble(), 2000 * random.nextDouble());
            }
    
            Scene scene = new Scene(root, 300, 250);
            primaryStage.setScene(scene);
            primaryStage.show();
    
            // run once to don't search for a first button manually
            handler.handle(null);
        }
    
        public static void main(String[] args) { launch(); }
    }
    

    【讨论】:

      【解决方案2】:

      我为这个案例创建了一个稍微优雅的版本。但是,我只能在 y 轴上进行测试。希望对你有帮助

      private static void ensureVisible(ScrollPane scrollPane, Node node) {
          Bounds viewport = scrollPane.getViewportBounds();
          double contentHeight = scrollPane.getContent().localToScene(scrollPane.getContent().getBoundsInLocal()).getHeight();
          double nodeMinY = node.localToScene(node.getBoundsInLocal()).getMinY();
          double nodeMaxY = node.localToScene(node.getBoundsInLocal()).getMaxY();
      
          double vValueDelta = 0;
          double vValueCurrent = scrollPane.getVvalue();
      
          if (nodeMaxY < 0) {
              // currently located above (remember, top left is (0,0))
              vValueDelta = (nodeMinY - viewport.getHeight()) / contentHeight;
          } else if (nodeMinY > viewport.getHeight()) {
              // currently located below
              vValueDelta = (nodeMinY + viewport.getHeight()) / contentHeight;
          }
          scrollPane.setVvalue(vValueCurrent + vValueDelta);
      }
      

      【讨论】:

      • 你的有什么不同?
      • 很好的答案,但我注意到 if 语句需要修复。当用户向下滚动时,滚动端口视口边界将具有负 minY 值。 if 语句应该说“if (nodeMaxY viewport.getHeight() + viewport.getMinY())” 至少这是成功的为我工作。
      【解决方案3】:

      要获得完美的快照,您需要考虑滚动条的开始和停止位置。 视口从 0(Bounds scollpane)的一半视口开始,并从最大边界停止一半视口。 bounds vs viewport picture

      所以: 半视口下方的节点 Y -> setVvalue 为 0 节点 Y 高于 maxheigh-half 视口 -> 将值设置为 1

      在这之间,我们需要计算总高度 -1viewport(half start half at end ) 和节点 y - half viewport。 然后(节点 y - 一半视口)/(总高度 -1 视口)

                      double heightViewPort = scrollPane.getViewportBounds().getHeight();
                      double heightScrollPane = scrollPane.getContent().getBoundsInLocal().getHeight();
                      double y = Label.getBoundsInParent().getMaxY();
                      if (y<(heightViewPort/2)){
                          scrollPane.setVvalue(0);
                          // below 0 of scrollpane
      
                      }else if ((y>=(heightViewPort/2))&(y<=(heightScrollPane-heightViewPort/2))){
                         // between 0 and 1 of scrollpane
                          scrollPane.setVvalue((y-(heightViewPort/2))/(heightScrollPane-heightViewPort));
                      }
                      else if(y>= (heightScrollPane-(heightViewPort/2))){
                          // above 1 of scrollpane
                          scrollPane.setVvalue(1);
      
                      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-19
        • 2021-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多