在 JScrollPane 中调整 JPanel 大小时保留相对鼠标位置
我正在调整 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();
}
}
I'm resizing a JPanel inside of a JScrollPane, and I want to make sure that the point on the JPanel where my mouse is currently located retains its position with respect to the JScrollPane after the resize (like Google maps does when you zoom in/out).
I find the mouse position on the JPanel, which lets me deal with the viewport being at various positions. I multiply it by the zoom factor so I know where the point will be after scaling. I then subtract the position of the mouse on the ScrollPane so that I know where the point was with respect to the viewable area. I'm doing something wrong however, and I just can't see what.
Example Code:
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试以当前大小的百分比形式查找鼠标位置,然后将其应用到新大小:
作为示例。 通过这种方式,您可以查看鼠标相对于滚动窗格的位置,并在 ZoomPanel 上保留该关系。
Try instead finding the position of the mouse as a percentage of the current size, then applying that to the new size:
as an example. In this way, you are looking at the mouse position relative to the scroll pane, and preserving that relationship on the zoomPanel.