0

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);
    }
}
7
  • 1) Make your zoom an int scale from 10 to 100 in 10 steps. 2) Draw or read your image at its maximum size. 3) Always reduce your maximum image down by the scale value. 4) Your origin formulas zoom in and out on the origin (upper left corner) of the image. Most people want to zoom based on the mouse pointer. You have to calculate the image size at each scale factor and figure out how to move the JScrollPane sliders so the mouse pointer point remains in the center of the JScrollPane. Commented Dec 20, 2023 at 21:51
  • Check out these two Stack Overflow answers: Answer 1, Answer 2. Commented Dec 20, 2023 at 22:03
  • Neither of those are quite what I'm looking for. The problem is somewhere in the JScrollPane and how it takes in the new scrolling coordinates with the formula I found on other questions. Commented Dec 20, 2023 at 22:28
  • Does anybody know where exactly in the JScrollBar that getValue() returns? Is it on the very left or right side of where the scrolling bar is on the JScrollBar's total length? Commented Dec 20, 2023 at 22:30
  • "Where it returns" doesn't make sense, unless you're asking about a change listener or other state listener. What it returns is the relative location of the viewport view within the viewport. Commented Dec 20, 2023 at 22:32

0

Browse other questions tagged or ask your own question.