2012-10-31 5 views
9

Ich muss die neue Position des Ansichtsfensters berechnen, wenn ich in ein Bild zoome.JScrollPane - Zoom relativ zur Mausposition

Die Benutzeroberfläche ist wie folgt aufgebaut:

  • ImagePanel zeichnet das Bild
  • ImagePanelWrapper ist ein JPanel Umwickeln des imagePanel
  • JScrollPane enthält die ImagePanelWrapper

Wenn ein- oder aus, wird der Zoomfaktor des ImagePanels geändert und die bevorzugte Größe des ImagePanels wird neu berechnet. Daher wird das Bild in diesem Fenster verschoben, obwohl das ImagePanel am selben Ansichtspunkt bleibt.

Die folgenden Methoden werden aufgerufen, wenn der Benutzer STRG gedrückt hält und das Mausrad verwendet. Der angegebene Punkt ist die vom MouseWheelListener bereitgestellte Cursorposition. Mit der Funktionalität in diesen Methoden bleibt das Bild beim Zoomen immer gleich oben links.

Das Problem ist, dass ich gerade nicht herausfinden kann, wie man sich relativ zur Maus bewegt, wie Paint.NET zum Beispiel. Irgendwelche Ideen?

/** 
* 
*/ 
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(); 
} 

Antwort

34

Wenn diese Annahmen zutreffen:

  • Der mitgelieferte Punkt ist relativ zur oberen linken Ecke des Bildfensters.
  • Die Abmessungen des Ansichtsfensters sind kleiner als das zugrunde liegende ImagePanel.

Dann kann das Ansichtsfenster so eingestellt werden, dass sich der Cursor über dem gleichen Punkt in dem Bild vor und nach dem Zoom-Vorgang, wenn auf die folgende Weise bewegt:

/** 
* 
*/ 
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(); 
} 

Hier ist die Mathematik für Vollständigkeit willen:

enter image description here

+1

+1 Awesome, Antwort. Das Beste, was ich seit einiger Zeit gesehen habe. – max

+0

Sie Sir verdienen ein großes Dankeschön :) – EyeSpy

+0

Ich habe eine ähnliche Frage. Ich versuche, AffineTransform zu verwenden, um dasselbe zu tun, und ich habe einige Mühe, die Mathematik von dieser Frage anzuwenden. Wenn du Zeit findest, könntest du mir helfen? http://stackoverflow.com/questions/37509908/zoom-in-at-mouse-cursor – bigblind

2

Sie sollten die Position des Mauszeigers mit point.x und point.y erhalten können, - finden Sie in der Dokumentation Pointhere. Entsprechend der MouseMotionEvent Dokumentation here sind die point.x und point.y relativ zu der Komponente unter der Maus (JScrollPane).

Sie können diese Werte in Ihre Berechnung einbeziehen. Ist das was du gesucht hast?