2012-10-31 13 views
9

Muszę obliczyć nową pozycję rzutni podczas powiększania obrazu.JScrollPane - Przybliżenie względem pozycji myszy

UI jest zbudowany w następujący sposób:

  • ImagePanel rysuje obraz
  • ImagePanelWrapper jest owijanie JPanel wokół imagePanel
  • JScrollPane zawiera ImagePanelWrapper

podczas powiększania lub out, współczynnik powiększenia ImagePanel zostanie zmieniony, a preferowany rozmiar ImagePanel zostanie ponownie obliczony. Dlatego obraz na tym panelu porusza się, mimo że ImagePanel pozostaje w tym samym punkcie widoku.

Następujące metody są wywoływane, gdy użytkownik przytrzymuje klawisz CTRL i używa kółka myszy. Podany punkt jest miejscem kursora dostarczonym przez MouseWheelListener. Dzięki funkcjonalności w tych metodach obraz jest już w tej samej górnej lewej pozycji podczas powiększania lub pomniejszania.

Problem polega na tym, że po prostu nie mogę wymyślić sposobu poruszania się względem myszy, na przykład Paint.NET. Jakieś pomysły?

/** 
* 
*/ 
public void zoomOut(Point point) { 
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f); 
    Point pos = this.getViewport().getViewPosition(); 

    int newX = (int) (pos.x * 0.9f); 
    int newY = (int) (pos.y * 0.9f); 
    this.getViewport().setViewPosition(new Point(newX, newY)); 

    this.imagePanel.revalidate(); 
    this.imagePanel.repaint(); 
} 

/** 
* 
*/ 
public void zoomIn(Point point) { 
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f); 
    Point pos = this.getViewport().getViewPosition(); 

    int newX = (int) (pos.x * 1.1f); 
    int newY = (int) (pos.y * 1.1f); 
    this.getViewport().setViewPosition(new Point(newX, newY)); 

    this.imagePanel.revalidate(); 
    this.imagePanel.repaint(); 
} 

Odpowiedz

34

Jeśli te założenia są prawdziwe:

  • Dostarczony Point jest w stosunku do lewego górnego rogu rzutni.
  • Wymiary rzutni są mniejsze niż podstawowy obraz w ImagePanelu.

Następnie rzutni można regulować tak, że kursor znajduje się w tym samym punkcie obrazu przed i po operacji powiększenia, jeśli przeniósł się w następujący sposób:

/** 
* 
*/ 
public void zoomOut(Point point) { 
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f); 
    Point pos = this.getViewport().getViewPosition(); 

    int newX = (int)(point.x*(0.9f - 1f) + 0.9f*pos.x); 
    int newY = (int)(point.y*(0.9f - 1f) + 0.9f*pos.y); 
    this.getViewport().setViewPosition(new Point(newX, newY)); 

    this.imagePanel.revalidate(); 
    this.imagePanel.repaint(); 
} 

/** 
* 
*/ 
public void zoomIn(Point point) { 
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f); 
    Point pos = this.getViewport().getViewPosition(); 

    int newX = (int)(point.x*(1.1f - 1f) + 1.1f*pos.x); 
    int newY = (int)(point.y*(1.1f - 1f) + 1.1f*pos.y); 
    this.getViewport().setViewPosition(new Point(newX, newY)); 

    this.imagePanel.revalidate(); 
    this.imagePanel.repaint(); 
} 

Oto matematyka dla kompletności 'sake:

enter image description here

+1

+1 Niesamowite, odpowiedź. Najlepsze, jakie widziałem od dłuższego czasu. – max

+0

Pan zasługuje na wielkie podziękowanie :) – EyeSpy

+0

Mam podobne pytanie. Próbuję użyć AffineTransform, aby zrobić to samo i mam problem z zastosowaniem matematyki z tego pytania. Jeśli znajdziesz czas, możesz mi pomóc? http://stackoverflow.com/questions/37509908/zoom-in-at-mouse-cursor – bigblind

2

Powinieneś być w stanie uzyskać położenie kursora myszy przy użyciu point.x i point.y - Zapoznaj się z dokumentacją herePoint. Zgodnie z dokumentacją MouseMotionEvent, point.x i point.y są w stosunku do komponentu pod mysz (JScrollPane).

Możesz włączyć te wartości do swoich obliczeń. Czy tego właśnie szukasz?

Powiązane problemy