Re: Zoom relative to mouse position




I've finally figured this out. Here's my code if you are interested:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ZoomDemo extends JPanel implements Runnable {

AffineTransform tx = new AffineTransform();

Rectangle2D.Double rect1 = new Rectangle2D.Double(100, 100, 30, 60);
Rectangle2D.Double rect2 = new Rectangle2D.Double(150, 250, 60, 40);

public ZoomDemo() {
this.addMouseWheelListener(new ZoomHandler());
}

@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
g2.draw(tx.createTransformedShape(rect1));
g2.setColor(Color.BLUE);
g2.draw(tx.createTransformedShape(rect2));
}

private class ZoomHandler implements MouseWheelListener {

double scale = 1.0;

public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {

Point2D p1 = e.getPoint();
Point2D p2 = null;
try {
p2 = tx.inverseTransform(p1, null);
} catch (NoninvertibleTransformException ex) {
// should not get here
ex.printStackTrace();
return;
}

scale -= (0.1 * e.getWheelRotation());
scale = Math.max(0.1, scale);

tx.setToIdentity();
tx.translate(p1.getX(), p1.getY());
tx.scale(scale, scale);
tx.translate(-p2.getX(), -p2.getY());

ZoomDemo.this.revalidate();
ZoomDemo.this.repaint();
}
}
}

public void run() {
JFrame f = new JFrame("Zoom Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(this);
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new ZoomDemo());
}
}












Amir Kouchekinia 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?

Thanks.

Here is my code:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

@SuppressWarnings("serial")
public class ZoomDemo extends JPanel {

AffineTransform tx = new AffineTransform();

Rectangle2D.Double rect = new Rectangle2D.Double(100, 100, 20, 30);

public ZoomDemo() {
this.addMouseWheelListener(new ZoomHandler());
}

@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;

Path2D.Double path;
g2.setColor(Color.RED);
path = new Path2D.Double(rect, tx);
g2.draw(path);
}

private class ZoomHandler implements MouseWheelListener {

Point oldPoint = null;

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 = AffineTransform.getTranslateInstance(p.getX(), p.getY());
tx.scale(scale, scale);
tx.translate(-p.getX(), -p.getY());

ZoomDemo.this.revalidate();
ZoomDemo.this.repaint();
}
}
}

public static void main(String[] args) {

JFrame f = new JFrame("ZoomDemo");
ZoomDemo zoomDemo = new ZoomDemo();
JScrollPane sp = new JScrollPane(zoomDemo);
f.getContentPane().add(sp);
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
.



Relevant Pages

  • Re: Graphics2D question
    ... Are the transformation operations (scale, translate, rotate...and what's the difference between "translate" and "origin"?) independent of the similar operations that would be set for the custom Swing component? ... you can certainly set the transformation for the Graphics2D based on whatever scaling and translation is necessary. ... Note that setting the Graphics2D transform is not the only approach. ... public void componentResized ...
    (comp.lang.java.programmer)
  • Re: AffineTransform.getScaleInstance question
    ... I want to scale the shape so that it seems ... It is if you create a Graphics from an Image that you are going to use for active rendering or for some other purpose. ... static boolean flip; ... public void mousePressed{ ...
    (comp.lang.java.gui)
  • Re: Select an area of an image...
    ... I am using an AffineTransform for the zoom in and out to scale and translate and draw the entire image so that it is displayed in the centre of the window. ... startX = me.getX; ... startY = me.getY; ... public void mouseReleased{ ...
    (comp.lang.java.programmer)
  • Cant get zooming into a selected area to work correctly.
    ... private BufferedImage _image; ... private Rectangle2D _rectDragBounds; ... public void componentResized{ ... public void setScale(float scale) ...
    (comp.lang.java.programmer)
  • Re: AffineTransform.getScaleInstance question
    ... and the way i defined my polygon. ... I want to scale the shape so that it seems ... It is if you create a Graphics from an Image ... public void mousePressed{ ...
    (comp.lang.java.gui)