Zoom to Point with JScrollPane

47 Views Asked by At

I found a few questions similar to the one I have, including this and this, but none that really answered the problem, and it's because I am using a JScrollPane. I found the code necessary for the formula; it's this:

originX -= mouseX / zoom - mouseX;
originY -= mouseY / zoom - mouseY;

So I tried plugging it into a JScrollPane:

JScrollPane scrollPane = drawFrame.scrollPane;
JScrollBar vert = scrollPane.getVerticalScrollBar(),
      horiz = scrollPane.getHorizontalScrollBar();
horiz.setValue(
     (int)(horiz.getValue() - (float)pastMouseX / zoom + pastMouseX)
);
vert.setValue(
     (int)(vert.getValue() - (float)pastMouseY / zoom + pastMouseY)
);

And the point at which the mouse zooms into is all over the place and I don't know why. Here is the minimal reproducible example:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
public class ResizeTest extends JFrame{
    JScrollPane scrollPane;
    BufferedImage image;
    int mouseX, mouseY;
    float zoom;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable(){
            @Override
            public void run(){
                new ResizeTest();
            }
        });
    }
    
    public ResizeTest(){
        zoom = 1;
        
        try{
            image = ImageIO.read(new File("a.jpg"));
        }catch(IOException e){
            e.printStackTrace();
        }
        
        JPanel panel = new JPanel(){
            @Override
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D)g;
                g2.scale(zoom, zoom);
                g2.drawImage(image, 0, 0, null);
                System.out.println(zoom);
            }
            
            @Override
            public Dimension getPreferredSize(){
                return new Dimension(image.getWidth(), image.getHeight());
            }
            
        };
        
        scrollPane = new JScrollPane(panel);
        
        panel.addMouseWheelListener(new MouseWheelListener(){
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                if(e.isControlDown()) {
                    if(e.getWheelRotation() > 0){
                        zoom /= 1.3333333333f;
                        if(zoom < 0.125)
                           zoom = 0.125f;
                    }
                    else if (e.getWheelRotation() < 0){
                        zoom *= 1.3333333333f;
                        if(zoom > 10)
                            zoom = 10;
                    }
                    if(zoom < 10){
                        JScrollBar vert = scrollPane.getVerticalScrollBar(),
                                horiz = scrollPane.getHorizontalScrollBar();
                        horiz.setValue(
                                (int)(horiz.getValue() - (float)mouseX / zoom + mouseX)
                        );
                        vert.setValue(
                                (int)(vert.getValue() - (float)mouseY / zoom + mouseY)
                        );
                    }

                } else {
                    scrollPane.dispatchEvent(e);
                }
                
                panel.repaint();
            }
        });
        
        panel.addMouseMotionListener(new MouseMotionListener(){
            @Override
            public void mouseDragged(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();
            }
        });
        
        setSize(new Dimension(1200,700));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(scrollPane);
        setVisible(true);
    }
    
    @Override
    public Dimension getPreferredSize(){
        return new Dimension(1200, 700);
    }
}
0

There are 0 best solutions below