2008-10-29 2 views
4

Я изменяю размер JPanel внутри JScrollPane, и я хочу убедиться, что точка на JPanel, где находится моя мышь, сохраняет свою позицию относительно JScrollPane после изменения размера (например, карты Google, когда вы увеличиваете/уменьшаете масштаб).Сохранять относительную позицию мыши при изменении размера JPanel в JScrollPane

Я нахожу положение мыши на 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(); 
    } 
} 

ответ

2

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

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

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

Смежные вопросы