Search code examples
javaswingzoominggraphics2d

Java Graphics2D - Zoom on mouse location


I have a jpanel that I draw on. I would like to be able to zoom in and out using the mousewheel, but I want to zoom to the location of the mouse, such that the point under the mouse stays the same. I have found some questions here on stackoverflow, but they did not work for me.

I got pretty close to doing what I want by implementing what is described here. Here is my code:

public class MyPanel extends JPanel {
...
    private double zoom = 1;
    private double zoom_old = 1;
    private int zoomPointX;
    private int zoomPointY;
...

   class CustomMouseWheelListener implements MouseWheelListener {
        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            zoomPointX = e.getX();
            zoomPointY = e.getY();
            if (e.getPreciseWheelRotation() < 0) {
                zoom -= 0.1;
            } else {
                zoom += 0.1;
            }
            if (zoom < 0.01) {
                zoom = 0.01;
            }
            repaint();
        }
    }
...
    protected void paintComponent(Graphics g) {
        Graphics2D g2D = (Graphics2D) g;
        super.paintComponent(g2D);
        if (zoom != zoom_old) {
            double scalechange = zoom - zoom_old;
            zoom_old = zoom;
            double offsetX = -(zoomPointX * scalechange);
            double offsetY = -(zoomPointY * scalechange) ;
            AffineTransform at = new AffineTransform();
            at.scale(zoom, zoom);
            at.translate(offsetX, offsetY);
            g2D.setTransform(at);
        }
        a_different_class_where_i_do_some_drawing.draw(g2D);
    }

}

This ALMOST does what I want. If I try to zoom, I notice that the position of the mouse is taken into account, so for example If I have my mouse on the left of the panel it will roughly zoom in on the left. However, it does not zoom exactly onto the mouse, so the point under the mouse still changes.

Can anyone help me fix this?

EDIT: Here is a picture of what is happening with the code posted above: I start out with the mouse on the blue square and then just scroll with the mouse wheel. As you can see, the mouse position if being changed: enter image description here


Solution

  • I solved the problem by implementing what is being described here

    Here is the updated code:

    public class MyPanel extends JPanel {
    ...
        private double zoom = 1;
        private int zoomPointX;
        private int zoomPointY;
    ...
    
       class CustomMouseWheelListener implements MouseWheelListener {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                zoomPointX = e.getX();
                zoomPointY = e.getY();
                if (e.getPreciseWheelRotation() < 0) {
                    zoom -= 0.1;
                } else {
                    zoom += 0.1;
                }
                if (zoom < 0.01) {
                    zoom = 0.01;
                }
                repaint();
            }
        }
    ...
        protected void paintComponent(Graphics g) {
            Graphics2D g2D = (Graphics2D) g;
            super.paintComponent(g2D);
            AffineTransform at = g2D.getTransform();
            at.translate(zoomPointX, zoomPointY);
            at.scale(zoom, zoom);
            at.translate(-zoomPointX, -zoomPointY);
            g2D.setTransform(at);
            a_different_class_where_i_do_some_drawing.draw(g2D);
        }
    
    }
    

    enter image description here