Сохранять относительное положение мыши при изменении размера JPanel в JScrollPane - PullRequest
4 голосов
/ 29 октября 2008

Я изменяю размер JPanel внутри JScrollPane и хочу убедиться, что точка на 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();
    }
}

1 Ответ

2 голосов
/ 29 октября 2008

Попробуйте вместо этого найти положение мыши в процентах от текущего размера, затем примените это к новому размеру:

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

в качестве примера. Таким образом, вы смотрите на положение мыши относительно панели прокрутки и сохраняете это отношение на zoomPanel.

...