提前致谢,
安迪
提前致谢,
安迪
我将尝试在没有代码的情况下解释这个问题,因为我认为这并不必要。
假设您的滚动窗格的内容高度为h
,视口的高度为v
。如果h=v
,则内容将完全适合视口,您将不需要滚动条。在这种情况下(使用不可移动的滚动条),要使元素居中,它需要位于滚动窗格内容的中心位置。您无法通过滚动将其移动到视口的中心位置。
现在将h
视为v
的两倍(即h=2v
)。在这种情况下,滚动窗格内容的上1/4和下1/4不能通过滚动居中。
(如果绝对需要通过滚动来居中任何组件,则应考虑填充您的内容窗格,但我们将在此处继续使用未填充的解决方案)
当您思考时,您会意识到滚动条的可能可滚动距离为h-v
,并且您将通过将vvalue
设置为1.0来滚动该距离。
要将点y
(这里的点y是滚动窗格内容窗格的坐标)居中,您可以使用以下vvalue:
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整个内容的大小(可滚动区域的宽度和高度,不仅仅是带滚动条的框架,而是完全的没有滚动条的情况下),以及居中对象在ScrollPane内容中的位置。
您可以通过以下方式获取内容大小:scrollPane.getContent().getBoundsInLocal().getHeight() or .getWidth()
以及您的对象的位置:node.getBoundsInParent().getMinY() or .getMinX()
- 对象的最小位置。您还可以获取其高度和宽度。
然后根据此公式计算出中心位置,并移动滚动条。
double vScrollBarPosition = scrollPane.getVMax() * (yPositionOfCenter / heightOfScrollPaneContent)
这里有一个关于如何居中旋转后的图片的示例。 代码是用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);
}