LoudPacks Posted September 21, 2016 Share 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; } } } Quote Link to comment Share on other sites More sharing options...
FrostBug Posted September 21, 2016 Share 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 Quote Link to comment Share on other sites More sharing options...
Th3 Posted September 21, 2016 Share 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(); Quote Link to comment Share on other sites More sharing options...