title: How do I make this panel zoom toward the middle of the panel?
body: <p>I have a JPanel with the code here.  I want the panel to zoom in towards the center of what's in the panel when I scroll with the mousewheel.  Currently, whenever I zoom in/out with the mouse wheel, the corner in the top left of the image stays in the same place.  I've had a difficult time finding a correct algorithm.  </p>
  
  <p>To zoom into the picture, the code uses an AffineTransform object which scales the image according to a double value which increases or decreases based on the movement of the mouse wheel. </p>
  
  <p>What also adds to the complexity is that the image can also be clicked and dragged around the panel.  If it is clicked and dragged, the zoom must still zoom in on what's in the center of the PANEL, and not the center of the actual image necessarily.</p>
  
  <p>Once again, the zooming should be done relative to the center point of the currently visible area. That is, as zooming occurs, the point at the center of the view should remain fixed.</p>
  
  <p>This is the code (and it's executable):</p>
  
  <pre><code>package clientgui;
  
  import java.awt.*;
  
  import javax.imageio.ImageIO;
  import javax.swing.*;
  
  import java.awt.event.*;
  import java.awt.geom.*;
  import java.awt.image.BufferedImage;
  import java.net.URL;
  
  import javax.swing.border.TitledBorder;
  
  public class MoveImageExample extends JFrame {
      ShowCanvas canvas;
  
      public MoveImageExample() throws Exception {
          super();
          Container container = getContentPane();
          canvas = new ShowCanvas(
                  "http://cdn.smosh.com/sites/default/files/bloguploads/funny-iphone-5-bruce-lee.jpg");
          container.setPreferredSize(new Dimension(canvas.getWidth(), canvas
                  .getHeight()));
          System.out.println("width = " + canvas.getWidth() + " height = "
                  + canvas.getHeight());
          container.add(canvas);
          pack();
          setVisible(true);
      }
  
      public static void main(String arg[]) throws Exception {
          new MoveImageExample();
      }
  }
  
  @SuppressWarnings("serial")
  class ShowCanvas extends JPanel {
      int imageX = 0, imageY = 0;
      int lastMouseX = 0, lastMouseY = 0;
      int centerX = 225;
      int centerY = 225;
      int canvasWidth = 450;
      int canvasHeight = 450;
      double scaleFactor = 1.0;
      boolean firstMouseDrag = true;
      BufferedImage image;
  
      public ShowCanvas(String imagePath) throws Exception {
          setBackground(Color.white);
          MouseMotionHandler mouseHandler = new MouseMotionHandler();
          addMouseMotionListener(mouseHandler);
          addMouseListener(mouseHandler);
          addMouseWheelListener(mouseHandler);
          URL url = new URL(imagePath);
          Image rawImage = ImageIO.read(url);
          image = new BufferedImage(rawImage.getWidth(this),
                  rawImage.getHeight(this), BufferedImage.TYPE_INT_ARGB);
          setSize(image.getWidth(), image.getHeight());
          Graphics2D g2 = image.createGraphics();
          g2.drawImage(rawImage, imageX, imageY, this);
      }
  
      public void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2D = (Graphics2D) g;
          g2D.setColor(Color.gray);
          g.fillRect(0, 0, image.getWidth(), image.getHeight());
          AffineTransform transformer = new AffineTransform();
          // translate the image back (using new scale factor)
          transformer.scale(scaleFactor, scaleFactor); // scale by 2x on x and y
                                                          // axes.
          transformer.translate(imageX / scaleFactor, imageY / scaleFactor);
          g2D.drawImage(image, transformer, this);
      }
  
      class MouseMotionHandler extends MouseMotionAdapter implements
              MouseListener, MouseWheelListener {
          public void mousePressed(MouseEvent e) {
              lastMouseX = e.getX();
              lastMouseY = e.getY();
          }
  
          public void mouseDragged(MouseEvent e) {
              int xDiff = e.getX() - lastMouseX;
              int yDiff = e.getY() - lastMouseY;
              imageX = imageX + xDiff;
              imageY = imageY + yDiff;
              lastMouseX = e.getX();
              lastMouseY = e.getY();
              repaint();
          }
  
          public void mouseWheelMoved(MouseWheelEvent e) {
              int notches = e.getWheelRotation();
              scaleFactor = scaleFactor + notches / 10.0;
              if (scaleFactor &lt; 0.5) {
                  scaleFactor = 0.5;
              } else if (scaleFactor &gt; 3.0) {
                  scaleFactor = 3.0;
              }
              repaint();
          }
  
          public void mouseReleased(MouseEvent e) {
          }
  
          public void mouseEntered(MouseEvent e) {
          }
  
          public void mouseExited(MouseEvent e) {
          }
  
          public void mouseClicked(MouseEvent e) {
          }
      }
  }
  </code></pre>