如何在 JScrollPane 中实现位置敏感缩放? [英] How do you implement position-sensitive zooming inside a JScrollPane?

查看:23
本文介绍了如何在 JScrollPane 中实现位置敏感缩放?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 JScrollPane 内实现位置敏感缩放.JScrollPane 包含一个带有自定义 paint 的组件,该组件将在分配的任何空间内绘制自己 - 因此缩放就像使用 MouseWheelListener 一样简单根据需要调整内部组件的大小.

I am trying to implement position-sensitive zooming inside a JScrollPane. The JScrollPane contains a component with a customized paint that will draw itself inside whatever space it is allocated - so zooming is as easy as using a MouseWheelListener that resizes the inner component as required.

但我也想放大(或缩小)一个点,以在结果放大(或缩小)视图中使该点尽可能居中(这就是我所说的位置敏感"缩放),类似于在谷歌地图中缩放的工作方式.我相信这之前已经做过很多次了 - 有没有人知道在 Java Swing 下做这件事的正确"方法吗?使用 Graphic2D 的转换而不是使用 JScrollPanes 会更好吗?

But I also want zooming into (or out of) a point to keep that point as central as possible within the resulting zoomed-in (or -out) view (this is what I refer to as 'position-sensitive' zooming), similar to how zooming works in google maps. I am sure this has been done many times before - does anybody know the "right" way to do it under Java Swing?. Would it be better to play with Graphic2D's transformations instead of using JScrollPanes?

示例代码如下:

package test;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class FPanel extends javax.swing.JPanel {

private Dimension preferredSize = new Dimension(400, 400);    
private Rectangle2D[] rects = new Rectangle2D[50];

public static void main(String[] args) {        
    JFrame jf = new JFrame("test");
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setSize(400, 400);
    jf.add(new JScrollPane(new FPanel()));
    jf.setVisible(true);
}    

public FPanel() {
    // generate rectangles with pseudo-random coords
    for (int i=0; i<rects.length; i++) {
        rects[i] = new Rectangle2D.Double(
                Math.random()*.8, Math.random()*.8, 
                Math.random()*.2, Math.random()*.2);
    }
    // mouse listener to detect scrollwheel events
    addMouseWheelListener(new MouseWheelListener() {
        public void mouseWheelMoved(MouseWheelEvent e) {
            updatePreferredSize(e.getWheelRotation(), e.getPoint());
        }
    });
}

private void updatePreferredSize(int n, Point p) {
    double d = (double) n * 1.08;
    d = (n > 0) ? 1 / d : -d;
    int w = (int) (getWidth() * d);
    int h = (int) (getHeight() * d);
    preferredSize.setSize(w, h);
    getParent().doLayout();
    // Question: how do I keep 'p' centered in the resulting view?
}

public Dimension getPreferredSize() {
    return preferredSize;
}

private Rectangle2D r = new Rectangle2D.Float();
public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.red);
    int w = getWidth();
    int h = getHeight();
    for (Rectangle2D rect : rects) {
        r.setRect(rect.getX() * w, rect.getY() * h, 
                rect.getWidth() * w, rect.getHeight() * h);
        ((Graphics2D)g).draw(r);
    }       
  }
}

推荐答案

经过测试,似乎有效...

Tested this, seems to work...

private void updatePreferredSize(int n, Point p) {
    double d = (double) n * 1.08;
    d = (n > 0) ? 1 / d : -d;

    int w = (int) (getWidth() * d);
    int h = (int) (getHeight() * d);
    preferredSize.setSize(w, h);

    int offX = (int)(p.x * d) - p.x;
    int offY = (int)(p.y * d) - p.y;
    setLocation(getLocation().x-offX,getLocation().y-offY);

    getParent().doLayout();
}

更新

这里解释一下:点p是鼠标相对于FPanel的位置.由于您正在缩放面板的大小,p 的位置(相对于面板的大小)将按相同的比例缩放.通过从缩放位置中减去当前位置,您可以在调整面板大小时获得点移动"的程度.然后只需将滚动窗格中的面板位置向相反方向移动相同的量即可将 p 放回鼠标光标下方.

Here is an explanation: the point p is the location of the mouse relative to the FPanel. Since you are scaling the size of the panel, the location of p (relative to the size of the panel) will scale by the same factor. By subtracting the current location from the scaled location, you get how much the point 'shifts' when the panel is resized. Then it is simply a matter of shifting the panel location in the scroll pane by the same amount in the opposite direction to put p back under the mouse cursor.

这篇关于如何在 JScrollPane 中实现位置敏感缩放?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆