【问题标题】:JScrollPane - Zoom relative to mouse positionJScrollPane - 相对于鼠标位置缩放
【发布时间】:2012-10-20 18:14:16
【问题描述】:

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

用户界面的构建如下:

  • ImagePanel 绘制图像
  • ImagePanelWrapper 是一个包裹在 imagePanel 周围的 JPanel
  • JScrollPane 包含 ImagePanelWrapper

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

当用户按住 CTRL 并使用鼠标滚轮时,会调用以下方法。给定的 point 是 MouseWheelListener 提供的光标位置。借助这些方法中的功能,图像在放大或缩小时已经保持在相同的左上角位置。

问题是我不知道如何相对于鼠标移动,例如 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();
}

【问题讨论】:

    标签: java swing mouse zooming jscrollpane


    【解决方案1】:

    如果这些假设成立:

    • 提供的 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();
    }
    

    为了完整起见,这里是数学:

    【讨论】:

    • 我也有类似的问题。我正在尝试使用 AffineTransform 做同样的事情,但我在应用这个问题的数学时遇到了一些麻烦。如果你有时间,你能帮帮我吗? stackoverflow.com/questions/37509908/zoom-in-at-mouse-cursor
    • 您的“缩放前”假设之前的缩放为 1.0(无缩放);如果不是呢? IOW:下次调用此代码时会发生什么?
    【解决方案2】:

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

    您可以将这些值合并到您的计算中。这就是你要找的东西吗?

    【讨论】:

      猜你喜欢
      • 2014-04-22
      • 2017-02-11
      • 1970-01-01
      • 2016-04-14
      • 2022-01-06
      • 2020-05-28
      • 1970-01-01
      • 2018-02-01
      • 2015-06-12
      相关资源
      最近更新 更多