LoudPacks Posted September 21, 2016 Posted September 21, 2016 I want to be able to zoom in using scaling but right now it scales relative to the top left corner and I want to be able to scale based on my mouse position. Does any one have any ideas on how I can make this happen? This is how it looks as of now, scaling into the top left corner. Code: import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MouseInfo; import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class PictureFrame { private ImageCanvas canvas; public PictureFrame(String filePath) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createFrame(filePath); } }); } public PictureFrame(Image image) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createFrame(image); } }); } private void createFrame(String filePath) { JFrame frame = new JFrame("Picture Frame Test"); frame.setSize(800, 600); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); canvas = new ImageCanvas(filePath, frame.getWidth(), frame.getHeight()); frame.getContentPane().add(canvas); frame.setVisible(true); } private void createFrame(Image image) { JFrame frame = new JFrame("Picture Frame Test"); frame.setSize(800, 600); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); canvas = new ImageCanvas(image, frame.getWidth(), frame.getHeight()); frame.getContentPane().add(canvas); frame.setVisible(true); } private class ImageCanvas extends JComponent { private Image image; private AffineTransform transformer = new AffineTransform(); ImageCanvas(String filePath, int width, int height) { try { image = ImageIO.read(new File(filePath)); setSize(width, height); EventListener eventListener = new EventListener(); addMouseListener(eventListener); addMouseWheelListener(eventListener); addMouseMotionListener(eventListener); } catch (IOException e) { System.out.println("Unable to read image file!"); } } ImageCanvas(Image image, int width, int height) { this.image = image; setSize(width, height); EventListener eventListener = new EventListener(); addMouseListener(eventListener); addMouseWheelListener(eventListener); addMouseMotionListener(eventListener); } public double getMinScale(){ double limitX = (double) canvas.getWidth() / (double) canvas.getImage().getWidth(null); double limitY = (double) canvas.getHeight() / (double) canvas.getImage().getHeight(null); return (limitX > limitY) ? limitX : limitY; } public Image getImage(){ return image; } public AffineTransform getTransformer(){ return transformer; } @[member=Override] protected void paintComponent(Graphics g) { try { Graphics2D graphics = (Graphics2D) g; graphics.setTransform(transformer); Point mouse = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(mouse, this); graphics.drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), null); graphics.setColor(Color.BLACK); graphics.fillRect(0, 0, 90, 15); graphics.setColor(Color.WHITE); graphics.drawString(String.format("X: %.0f Y: %.0f", mouse.getX(), mouse.getY()), 10, 10); Thread.sleep(15); } catch (InterruptedException e) { e.printStackTrace(); } } } private class EventListener implements MouseListener, MouseWheelListener, MouseMotionListener { private Point startPoint, endPoint; private double deltaX, deltaY; @[member=Override] public void mouseWheelMoved(MouseWheelEvent e) { AffineTransform transformer = canvas.getTransformer(); if(e.getWheelRotation() < 0) transformer.setToScale(transformer.getScaleX() + .05, transformer.getScaleY() + .05); else transformer.setToScale(Math.max(canvas.getMinScale(), transformer.getScaleX() - .05), Math.max(canvas.getMinScale(), transformer.getScaleY() - .05)); transformer.translate(deltaX, deltaY); canvas.repaint(); } @[member=Override] public void mouseClicked(MouseEvent e) { } @[member=Override] public void mousePressed(MouseEvent e) { startPoint = e.getPoint(); } @[member=Override] public void mouseReleased(MouseEvent e) { } @[member=Override] public void mouseEntered(MouseEvent e) { } @[member=Override] public void mouseExited(MouseEvent e) { } @[member=Override] public void mouseDragged(MouseEvent e) { AffineTransform transformer = canvas.getTransformer(); try { endPoint = e.getPoint(); Point dragStart = transformPoint(startPoint); Point dragEnd = transformPoint(endPoint); /* double dx = dragEnd.getX() - dragStart.getX(); double dy = dragEnd.getY() - dragStart.getY(); deltaX += dx; deltaY += dy; */ double deltaW = (double) canvas.getWidth() - (double) canvas.getImage().getWidth(null) * transformer.getScaleX(); double deltaH = (double) canvas.getHeight() - (double) canvas.getImage().getHeight(null) * transformer.getScaleY(); double px = Math.max(deltaW, Math.min(0, deltaX + (dragEnd.getX() - dragStart.getX()))); double dx = px - deltaX; double py = Math.max(deltaH, Math.min(0, deltaY + (dragEnd.getY() - dragStart.getY()))); double dy = py - deltaY; deltaX = px; deltaY = py; transformer.translate(dx, dy); startPoint = endPoint; endPoint = null; } catch (NoninvertibleTransformException ex) { ex.printStackTrace(); } canvas.repaint(); } @[member=Override] public void mouseMoved(MouseEvent e) { canvas.repaint(); } private Point transformPoint(Point p1) throws NoninvertibleTransformException{ AffineTransform transformer = canvas.getTransformer(); AffineTransform inverse = transformer.createInverse(); Point p2 = new Point(); inverse.transform(p1, p2); return p2; } } }
FrostBug Posted September 21, 2016 Posted September 21, 2016 (edited) I reckon you should translate the transformed image according to your mouse. Graphics2D graphics = (Graphics2D) g; graphics.setTransform(transformer); Point mouse = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(mouse, this); > graphics.translate(-mouse.getX() * graphics.getTransform().getScaleX(), -mouse.getY() * graphics.getTransform().getScaleY()); graphics.drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), null); > graphics.translate(mouse.getX() * graphics.getTransform().getScaleX(), mouse.getY() * graphics.getTransform().getScaleY()); graphics.setColor(Color.BLACK); graphics.fillRect(0, 0, 90, 15); graphics.setColor(Color.WHITE); graphics.drawString(String.format("X: %.0f Y: %.0f", mouse.getX(), mouse.getY()), 10, 10); Just a guess tho, haven't tried compiling your code EDIT: remember to translate back Edited September 21, 2016 by FrostBug
Th3 Posted September 21, 2016 Posted September 21, 2016 try something like this AffineTransform transformer = canvas.getTransformer(); Point p = e.getPoint(); int mouseX = p.x; int mouseY = p.y; double zoom = e.getUnitsToScroll() < 0 ? 1.05 : 1 / 1.05; deltaX = (int) ((transformer.getTranslateX() * zoom) - ((mouseX * zoom) - mouseX)); deltaY = (int) ((transformer.getTranslateY() * zoom) - ((mouseY * zoom) - mouseY)); transformer.setToScale(transformer.getScaleX() * zoom, transformer.getScaleY() * zoom); transformer.translate(deltaX, deltaY); canvas.repaint();