Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX滚动窗格以编程方式移动视口居中内容_Java_Javafx 2_Viewport_Panning_Scrollpane - Fatal编程技术网

JavaFX滚动窗格以编程方式移动视口居中内容

JavaFX滚动窗格以编程方式移动视口居中内容,java,javafx-2,viewport,panning,scrollpane,Java,Javafx 2,Viewport,Panning,Scrollpane,我可以使用setVvalue(double)和setHvalue(double)方法在JavaFX滚动窗格中移动视口。我正在努力做的是根据滚动窗格内容中的特定节点的位置将其居中。我尝试了localToScene()和boundsInParent()的各种组合。我读了很多书,看到了这个例子 这是接近但不居中的对象只是把他们可见。内置的鼠标平移功能非常出色,但我正在为编程平移带来恶劣天气 最终,我还需要能够进行缩放,以便将实际形状放入一个组中,并将该组添加到滚动窗格内容中。我想我应该在组上进行缩放

我可以使用setVvalue(double)和setHvalue(double)方法在JavaFX滚动窗格中移动视口。我正在努力做的是根据滚动窗格内容中的特定节点的位置将其居中。我尝试了localToScene()和boundsInParent()的各种组合。我读了很多书,看到了这个例子

这是接近但不居中的对象只是把他们可见。内置的鼠标平移功能非常出色,但我正在为编程平移带来恶劣天气

最终,我还需要能够进行缩放,以便将实际形状放入一个组中,并将该组添加到滚动窗格内容中。我想我应该在组上进行缩放,再次我需要能够围绕组的中心进行缩放,这样我们就可以重新操纵和识别当前的中心位置。任何可以提供的指针或示例都将非常感谢。上面链接中的代码示例是一个很好的SSCCE

提前感谢,


安迪

我知道,现在有点晚了,但也许有人会发现它很有用。:)

至于定心,这不是一项艰巨的任务,它只需要一点点的数学知识。你需要两样东西。滚动窗格的整个内容的大小(可滚动区域的宽度和高度,不仅是带有滚动条的框架的宽度和高度,而且是完整的,就像没有滚动条一样),以及滚动窗格内容内居中对象的位置

内容大小如下:
scrollPane.getContent().getBoundsInLocal().getHeight()或.getWidth()

对象的位置:
节点.getBoundsInParent().getMinY()或.getMinX()
-对象的最小位置。你也可以得到它的高度和宽度

然后根据这个公式计算中心位置并移动滚动条


double-vScrollBarPosition=scrollPane.getVMax()*(yPositionOfCenter/heightOfScrollPaneContent)
我将尝试在没有代码的情况下解释这一点,因为我认为这里没有必要这样做

假设滚动窗格的内容具有高度
h
,而视口的高度为
v
。如果
h=v
,则内容将完全适合视口,并且不需要滚动条。在这种情况下(使用不可移动的滚动条),要使元素居中,需要将其放置在滚动窗格内容的中心。不能通过滚动将其移动到视口的中心

现在考虑<代码> h <代码>是代码< v>代码>的两倍(即<代码> h=2v)。在这种情况下,滚动窗格内容的上1/4和下1/4不能通过滚动居中

(如果您绝对需要通过滚动来定位任何组件,您应该考虑填充内容窗格,但我们将继续使用未填充的解决方案)

仔细想想,你会发现滚动条可能的滚动距离是
h-v
,你可以通过将
vvalue
设置为1.0来滚动该数值

要居中点y(此处点y是滚动窗格内容窗格的坐标),可以使用以下V值:

vvalue = (y - 0.5 * v) / (h - v) 
此表达式的命名符是当点y位于视口内的中心时,视口顶部显示的内容的y坐标。分母是可滚动的总距离

编辑:还是添加一些代码吧

public void centerNodeInScrollPane(ScrollPane scrollPane, Node node) {
    double h = scrollPane.getContent().getBoundsInLocal().getHeight();
    double y = (node.getBoundsInParent().getMaxY() + 
                node.getBoundsInParent().getMinY()) / 2.0;
    double v = scrollPane.getViewportBounds().getHeight();
    scrollPane.setVvalue(scrollPane.getVmax() * ((y - 0.5 * v) / (h - v)));
}
(请注意,这假设该节点是scrollpane的contentpane的直接子节点)


希望这有帮助!:)

下面是一个关于如何将已旋转的图片居中的示例。 代码使用Scala,因此适用于ScalaFX,但JavaFX和Java开发人员将能够阅读/使用它:

  def turnPic(angle:Int) {
    val virtualSurfaceMultiplier = 8.0;
    currentAngle = ( floor((currentAngle % 360) / 90) * 90 + angle + 360 ) % 360;
    imageView.rotate = currentAngle;
    val orientationSwitched = (currentAngle / 90) % 2 > 0;
    val width= scrollPane.getViewportBounds().getWidth();
    val height= scrollPane.getViewportBounds().getHeight();
    val viewPort = new Rectangle2D(0, 0, image.width.value, image.height.value);
    imageView.setViewport(viewPort);
    imageView.fitHeight.value = virtualSurfaceMultiplier * height;
    imageView.fitWidth.value = 0 //virtualSurfaceMultiplier * width;
    def centerV(picHeight:Double) {
      val node  = scrollPane.getContent();
      val totalHeight = scrollPane.getContent().getBoundsInLocal().getHeight();
      val offsetToCenter = (node.getBoundsInParent().getMaxY() + node.getBoundsInParent().getMinY()) / 2.0;
      val viewportWidth = scrollPane.getViewportBounds().getHeight();
      val res = (scrollPane.getVmax() * ((offsetToCenter - 0.5 * picHeight * zoomFactor) / (totalHeight - picHeight * zoomFactor)));
      scrollPane.setVvalue(res);
    }
    def centerH(picWidth:Double) {
      val node  = scrollPane.getContent();
      val totalWidth = scrollPane.getContent().getBoundsInLocal().getWidth();
      val offsetToCenter = (node.getBoundsInParent().getMaxX() + node.getBoundsInParent().getMinX()) / 2.0;
      val viewportWidth = scrollPane.getViewportBounds().getWidth();
      val res = (scrollPane.getHmax() * ((offsetToCenter - 0.5 * picWidth * zoomFactor) / (totalWidth - picWidth * zoomFactor)));
      scrollPane.setHvalue(res);
      System.err.println(s"trace centerH> $FILE:$LINE:" + " totalWidth:" + totalWidth + " offsetToCenter=" + offsetToCenter + " vWidth=" + viewportWidth + "res=" + res);
    }
    if (orientationSwitched) {
      zoomFactor = 1.0 / (virtualSurfaceMultiplier * image.width.value / image.height.value);
      centerH(height);
      centerV(width);
    }
    else
    {
      zoomFactor = 1.0 / virtualSurfaceMultiplier;
      centerH(width);
      centerV(height);
    }
    imageView.setScaleX(zoomFactor);
    imageView.setScaleY(zoomFactor);
  }

嗯,在我看来,如果问题真的很简单,提问者是个白痴,或者问题真的很难,没有人会费心去解答,那么问题就不会在StackOverflow得到回答!我很高兴被告知我是个白痴!!这不会精确地居中显示组件,因为您假设滚动窗格可以在其内容窗格的整个高度上滚动。创建答案时需要格式化代码,这是完全不可读的。谢谢,即使节点不是滚动窗格的直接子节点,这也能很好地工作:我在两者之间有一个固定面板。