Keep relative mouse position when resizing JPanel in JScrollPane

I am resizing the JPanel inside the JScrollPane, and I want to make sure that the point on the JPanel where my mouse is located maintains its position relative to the JScrollPane after resizing (for example, a Google map when you zoom in / out).

I find the mouse position on JPanel, which allows me to deal with the viewport in different positions. I multiply it by the scaling factor, so I know where the point will be after scaling. Then I subtract the mouse position on the ScrollPane so that I know where the point was in relation to the scope. However, I am doing something wrong and I just don’t see that.

Code example:

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; public class Test { public static void main(String[] in) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new Test(); } }); } public Test() { final JFrame frame = new JFrame(); final ScalablePanel child = new ScalablePanel(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(child, BorderLayout.CENTER); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } } class ScalablePanel extends JScrollPane implements MouseWheelListener { final double ZOOM_IN_FACTOR = 1.1; final double ZOOM_OUT_FACTOR = 0.9; final JPanel zoomPanel = new JPanel(); public ScalablePanel() { final javax.swing.JLabel marker = new javax.swing.JLabel("Testing the mouse position on zoom"); marker.setHorizontalAlignment(javax.swing.JLabel.CENTER); zoomPanel.setLayout(new BorderLayout()); zoomPanel.add(marker,BorderLayout.CENTER); getViewport().setView(zoomPanel); setPreferredSize(new Dimension(300,300)); addMouseWheelListener(this); } public void mouseWheelMoved(final MouseWheelEvent e) { if (e.isControlDown()) { if (e.getWheelRotation() < 0) zoomIn(e); else zoomOut(e); e.consume(); } } public void zoomIn(final MouseWheelEvent e) { // Get the mouse position with respect to the zoomPanel final Point pointOnZoomPanel = SwingUtilities.convertPoint( e.getComponent(), e.getPoint(), zoomPanel); // Resize panel final Dimension currSize = zoomPanel.getSize(); zoomPanel.setPreferredSize( new Dimension( (int)(currSize.width * ZOOM_IN_FACTOR), (int)(currSize.height * ZOOM_IN_FACTOR) )); // Find out where our point on the zoom panel is now that we've resized it final Point newViewPos = new Point(); newViewPos.x = (int)(ZOOM_IN_FACTOR * pointOnZoomPanel.x - e.getPoint().x); newViewPos.y = (int)(ZOOM_IN_FACTOR * pointOnZoomPanel.y - e.getPoint().y); // Move the viewport to the new position to keep the area our mouse was in the same spot getViewport().setViewPosition(newViewPos); zoomPanel.revalidate(); } public void zoomOut(final MouseWheelEvent e) { // Get the mouse position with respect to the zoomPanel final Point pointOnZoomPanel = SwingUtilities.convertPoint( e.getComponent(), e.getPoint(), zoomPanel); // Resize panel final Dimension currSize = zoomPanel.getSize(); zoomPanel.setPreferredSize( new Dimension( (int)(currSize.width * ZOOM_OUT_FACTOR), (int)(currSize.height * ZOOM_OUT_FACTOR) )); // Find out where our point on the zoom panel is now that we've resized it final Point newViewPos = new Point(); newViewPos.x = (int)(ZOOM_OUT_FACTOR * pointOnZoomPanel.x - e.getPoint().x); newViewPos.y = (int)(ZOOM_OUT_FACTOR * pointOnZoomPanel.y - e.getPoint().y); // Move the viewport to the new position to keep the area our mouse was in the same spot getViewport().setViewPosition(newViewPos); zoomPanel.revalidate(); } } 
+4
source share
1 answer

Instead, try to find the mouse position as a percentage of the current size, and then apply it to the new size:

 newViewPos.x = (int)((ZOOM_IN_FACTOR * currSize.width) * (e.getPoint().x/(double)currSize.width)); 

as an example. Thus, you look at the position of the mouse relative to the scroll area and save this ratio on the zoomPanel.

+2
source

All Articles