JScrollPane – 相对于鼠标位置进行缩放

我需要在放大图像时计算视口的新位置。

UI构建如下:

  • ImagePanel绘制图像
  • ImagePanelWrapper是围绕imagePanel的JPanel
  • JScrollPane包含ImagePanelWrapper

放大或缩小时,ImagePanel的缩放系数会发生变化,并且会重新计算ImagePanel的首选大小。 因此,即使ImagePanel停留在相同的视口点,此面板上的图像也会移动。

当用户按住CTRL并使用鼠标滚轮时,将调用以下方法。 给定的是MouseWheelListener提供的光标位置。 通过这些方法的function,当放大或缩小时,图像已经停留在相同的左上角位置。

问题是我只是想弄清楚如何相对于鼠标移动,例如Paint.NET。 有任何想法吗?

/** * */ public void zoomOut(Point point) { this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f); Point pos = this.getViewport().getViewPosition(); int newX = (int) (pos.x * 0.9f); int newY = (int) (pos.y * 0.9f); this.getViewport().setViewPosition(new Point(newX, newY)); this.imagePanel.revalidate(); this.imagePanel.repaint(); } /** * */ public void zoomIn(Point point) { this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f); Point pos = this.getViewport().getViewPosition(); int newX = (int) (pos.x * 1.1f); int newY = (int) (pos.y * 1.1f); this.getViewport().setViewPosition(new Point(newX, newY)); this.imagePanel.revalidate(); this.imagePanel.repaint(); } 

如果这些假设成立:

  • 提供的Point相对于视口的左上角。
  • 视口的尺寸小于底层的ImagePanel。

然后可以调整视口,以便在缩放操作之前和之后光标位于图像中的同一点上,如果按以下方式移动:

  /** * */ public void zoomOut(Point point) { this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f); Point pos = this.getViewport().getViewPosition(); int newX = (int)(point.x*(0.9f - 1f) + 0.9f*pos.x); int newY = (int)(point.y*(0.9f - 1f) + 0.9f*pos.y); this.getViewport().setViewPosition(new Point(newX, newY)); this.imagePanel.revalidate(); this.imagePanel.repaint(); } /** * */ public void zoomIn(Point point) { this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f); Point pos = this.getViewport().getViewPosition(); int newX = (int)(point.x*(1.1f - 1f) + 1.1f*pos.x); int newY = (int)(point.y*(1.1f - 1f) + 1.1f*pos.y); this.getViewport().setViewPosition(new Point(newX, newY)); this.imagePanel.revalidate(); this.imagePanel.repaint(); } 

这是完整性的数学计算:

在此处输入图像描述

您应该能够使用point.xpoint.y获取鼠标指针的位置 – 请参阅此处的Point文档。 根据这里的MouseMotionEvent文档, point.xpoint.y是相对于鼠标下的组件( JScrollPane )。

您可以将这些值合并到计算中。 这有点像你在找什么?