Re: Zoom relative to mouse position
In article <IOqYj.2253$l97.606@flpi144.ffdc.sbc.com>,
Amir Kouchekinia <amir_nospam@pyrus_nospam.us> wrote:
Hi,
I am trying to figure out how to zoom relative to the mouse pointer
position. Below, please find my sample code.
When I initially position the mouse pointer on one corner of the red
rectangle and use the mouse wheel, I am able to zoom in and out as
expected. As soon as I move the pointer position, let's say to another
corner of the red rectangle, and try to zoom in or out, my position
relative to the rectangle shifts around.
I think I may be missing a transform or two. In another attempt, in the
mouseWheelMoved method, I inverted tx from the previous iteration and
transformed the mouse position p with the inverted transform before
recalculating the new transform; but the behavior got more erratic.
Any help is greatly appreciated. What am I missing here?
You want to transform a Shape's coordinates, but the normal
concatenation of transformations is arranged for a different goal.
Recalling that matrix multiplication is _not_ commutative, if you want
to scale then translate, you have to apply then in reverse order. See
concatenate() and preConcatenate(), as well as the scaled arrow thread
in this group.
Is this the effect you wanted? [Path2D replaced by Shape for 5.0 users.]
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class ZoomDemo extends JPanel {
AffineTransform tx = new AffineTransform();
Rectangle2D.Double rect = new Rectangle2D.Double(-15, -30, 30, 60);
public ZoomDemo() {
this.addMouseWheelListener(new ZoomHandler());
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
Shape shape = tx.createTransformedShape(rect);
g2.draw(shape);
}
private class ZoomHandler implements MouseWheelListener {
double scale = 1.0;
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
scale += (.1 * e.getWheelRotation());
scale = Math.max(0.1, scale);
Point p = e.getPoint();
tx.setToIdentity();
tx.translate(p.getX(), p.getY());
tx.scale(scale, scale);
ZoomDemo.this.revalidate();
ZoomDemo.this.repaint();
}
}
}
public static void main(String[] args) {
JFrame f = new JFrame("ZoomDemo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ZoomDemo zoomDemo = new ZoomDemo();
f.getContentPane().add(zoomDemo);
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
John
--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews