我正在调整JScrollPane内部的JPanel的大小,并且我想确保调整大小后,JPanel上鼠标当前所在的点相对于JScrollPane的位置保持不变(就像Google地图在放大/出来)。
我在JPanel上找到了鼠标的位置,这使我可以处理处于不同位置的视口。我将其乘以缩放系数,以便知道缩放后的点在哪里。然后,我减去鼠标在ScrollPane上的位置,以便知道该点相对于可视区域的位置。但是我做错了,我看不到。
示例代码:
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();
}
}
最佳答案
尝试以当前大小的百分比找到鼠标的位置,然后将其应用于新大小:
newViewPos.x = (int)((ZOOM_IN_FACTOR * currSize.width) * (e.getPoint().x/(double)currSize.width));
举个例子。这样,您正在查看鼠标相对于滚动窗格的位置,并将该关系保留在zoomPanel上。