3

I've got a JPanel I'm drawing onto and I'm trying to get it so that you can use the mouse wheel to "zoom" in and out by modifying the variable scale. Right now what happens is you can zoom in or out but all of the drawing shifts to the right and downwards when you zoom in and then back up and left when zooming out.

I want to make it so that it adjusts as if you were zooming in on the point at the center of the JPanel but I can't figure out how to calculate the right offset to translate by…

Anybody got an idea of how to do this, or even better a cleaner way of achieving this whole pan and zoom ability?

I am basically plotting a bunch of coordinates that came from a system where 0,0 is in the lower left corner and fall between the bounds:

xMin = 661208
xMax = 662618

yMin = 4291657
yMax = 4293285

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;

    double scale = details.getScale();
    double xOffset = details.getxOffset();
    double yOffset = details.getyOffset();

    g2.scale(scale, -scale);

    // Dividing offset by scale makes panning 1:1 with the cursor still. yMax to account for the
    // fact we needed to flip around the y axis to make it right-side up.
    g2.translate((-xMin + xOffset / scale), (-yMax + yOffset / scale));

    // Code to draw stuff goes here.  It uses coordinates between xMin-xMax and yMin-yMax to draw.
    .
    .
    .
}
Kevin Herron
  • 6,500
  • 3
  • 26
  • 35
  • This question might help you [http://stackoverflow.com/questions/690871/affinetransform-scaling-a-shape-from-its-center](http://stackoverflow.com/questions/690871/affinetransform-scaling-a-shape-from-its-center) – Pierre Sep 22 '09 at 08:03

1 Answers1

-1

Here is an example with the wheel:

 public class GraphicsOnly extends JPanel implements MouseWheelListener {
      Shape[] shapes;
      Dimension size;
      double scale = 1.0;
      private static int source = 100;
      public GraphicsOnly() {
        addMouseWheelListener(this);
        size = new Dimension(10,10);
        setBackground(new Color(240,200,200));
    }



    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        if(shapes == null) initShapes();
        // Keep shapes centered on panel.
        double x = (getWidth()  - scale*size.width)/2;
        double y = (getHeight() - scale*size.height)/2;
        AffineTransform at = AffineTransform.getTranslateInstance(x, y);
        at.scale(scale, scale);
        g2.setPaint(Color.blue);
        g2.draw(at.createTransformedShape(shapes[0]));
        g2.setPaint(Color.green.darker());
        g2.draw(at.createTransformedShape(shapes[1]));
        g2.setPaint(new Color(240,240,200));
        g2.fill(at.createTransformedShape(shapes[2]));
        g2.setPaint(Color.red);
        g2.draw(at.createTransformedShape(shapes[2]));
    }

    public Dimension getPreferredSize() {
        int w = (int)(scale*size.width);
        int h = (int)(scale*size.height);
        return new Dimension(w, h);
    }

    private void initShapes() {
        shapes = new Shape[3];
        int w = getWidth();
        int h = getHeight();
        shapes[0] = new Rectangle2D.Double(w/16, h/16, w*7/8, h*7/8);
        shapes[1] = new Line2D.Double(w/16, h*15/16, w*15/16, h/16);
        shapes[2] = new Ellipse2D.Double(w/4, h/4, w/2, h/2);
        size.width = w;
        size.height = h;
    }


    public static void main(String[] args) {
        GraphicsOnly app = new GraphicsOnly();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new JScrollPane(app));
        f.setSize(400, 400);
        f.setLocation(200,200);
        f.setVisible(true);
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        // TODO Auto-generated method stub
        if(e.getWheelRotation() >0){
            source = source-e.getScrollAmount();
        }else{
            source = source+e.getScrollAmount();
        }
        scale = source/100.0;
        System.out.println(scale);
        repaint();
        revalidate();
    }
}
Timothy Truckle
  • 15,071
  • 2
  • 27
  • 51