Frage

Der Code, den ich hier habe, ist ein Mouseadapter mit für den Benutzer zu „zeichnen“ einen Rahmen um den Bereich eines Bildes zu hören, dass sie den vergrößernden möchte und das Verhältnis der Box auf das Bild zu berechnen. Es ändert die Größe dann das Bild auf dem berechneten Verhältnis. Dieser Teil funktioniert.

Das Problem, das ich habe ist, so dass die JScrollPane Ansicht erscheinen, als ob es immer noch an der gleichen Position oben links ist, nachdem das Bild angepasst wurde. Ich habe mehrere Methoden versucht, die nahe zu dem Ergebnis gekommen zu sein scheinen möchte ich aber nicht genau.

Dies ist der Zuhörer, die das Skalenverhältnis findet und setzen die Position:

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.Graphics;
import java.awt.Point;

import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.JComponent;

public class DynamicZoom extends MouseAdapter {

private Point start;
private Point end;
private double zoom = 1.0;
private JScrollPane pane;
private JViewport port;


public void mousePressed(MouseEvent e) {
    if(e.getButton() == MouseEvent.BUTTON1) {
        this.pane = (JScrollPane)e.getSource();
        this.port = pane.getViewport();
        start = e.getPoint();
    }
}

public void mouseReleased(MouseEvent e) {
    if(this.pane != null) {
        Point curr = this.port.getViewPosition();
        end = e.getPoint();

        ImageComponent canvas = (ImageComponent)this.port.getView();
        zoom = canvas.getScale();
        double factor = 0.0;
        double selectedWidth = Math.abs(end.getX() - start.getX());
        double selectedHeight = Math.abs(end.getY() - start.getY());
        if(selectedWidth > selectedHeight)
            factor = this.port.getWidth() / selectedWidth;
        else
            factor = this.port.getHeight() / selectedHeight;

        zoom *= factor;
        int x = (int)((start.x+curr.x)*zoom);
        int y = (int)((start.y+curr.y)*zoom);

        Point point = new Point(x, y);

        ((ImageComponent)(this.port.getView())).setScale(zoom);

        ResizeViewport.resize(pane);
        this.port.setViewPosition(point);
    }
}

public void mouseDragged(MouseEvent e) {
    if(this.pane != null) {
        Graphics g = this.port.getGraphics();
        int width = this.start.x - e.getX();
        int height = this.start.y - e.getY();

        int w = Math.abs( width );
        int h = Math.abs( height );
        int x = width < 0 ? this.start.x : e.getX();
        int y = height < 0 ? this.start.y : e.getY();
        g.drawRect(x, y, w, h);
        this.port.repaint();
    }
}

}

Dies ist die ImageComponent Verändern der Größe und zeigt das Bild:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;

public class ImageComponent extends JComponent {
private static final long serialVersionUID = 1975488835382044371L;
private BufferedImage img = null;

private double scale = 0.0;

public ImageComponent() {}

public ImageComponent(BufferedImage img) {
    this.displayPage(img);
}

@Override
public void paint(Graphics g) {
    Graphics2D g2 = ((Graphics2D)g);
    if(this.img != null) {
        int width = (int)(this.img.getWidth() * this.scale);
        int height = (int)(this.img.getHeight() * this.scale);
        this.setPreferredSize(new Dimension(width, height));
        g2.drawImage(this.img, 0, 0, width, height, null, null);
        g2.dispose();
    }
}

public void displayPage(BufferedImage pic) {
    if(img != null) {
        this.img = pic;
    }
}

public BufferedImage getPage() {
    return this.img;
}

public void setScale(double ratio) {
    if(ratio > .04) {
        this.scale = ratio;
        this.repaint();
    }
}

public double getScale() {
    return this.scale;
}
}

Die ResizeViewport Kräfte das Ansichtsfenster den gesamten ImageComponent zu zeigen, wenn es hochskaliert wird, weil sonst wird es auf die Größe des Bildes Clip, dass es vorher war:

import java.awt.Dimension;

import javax.swing.JScrollPane;
public class ResizeViewport {
public static void resize(JScrollPane scroll) {
    int vw = scroll.getWidth()-scroll.getVerticalScrollBar().getWidth();
    int vh = scroll.getHeight()-scroll.getHorizontalScrollBar().getHeight();
    scroll.getViewport().setViewSize(new Dimension(vw, vh));
}
}
War es hilfreich?

Lösung

Es stellt sich heraus, es ist nichts falsch mit der Mathematik verwendet wird, ist die Position oder die Art, wie ich den Code entworfen zu berechnen. Das Problem war, dass der ImageComponent noch in einem anderen Thread zu malen, wenn die Position berechnet wurde; daher Rückkehr "false" Werte für die getWidth () und getHeight () -Methoden. Ich löste das Problem mit dem folgenden Code:

EventQueue.invokeLater(new Runnable() {
   public void run() {
      port.setViewPosition(new Point(x,y));
   }
});

Dies ermöglicht es, das Gemälde zu beenden, bevor Sie versuchen, die Größe des Bildes und die Einstellung der Position in der JScrollPane zu berechnen. Problem gelöst. Ich möchte noch einen Dank zu den Menschen werfen, die die Zeit für dieses Problem zumindest Überprüfung nahmen.

Andere Tipps

Ich hatte ein ähnliches Problem, aber manchmal wurde die Tafel gemalt falsch das erste Mal nach Größe ändern, nach Stunden versucht, eine Abhilfe, die ich eine Lösung gefunden!

Nach einer Resize der Platte in der scrollpane ist es am besten, indem Sie auf null zu zerstören Ansichtsfenster, und dann Platte wieder scrollpane hinzufügen, die ein neues Ansichtsfenster neu werden und alles funktioniert!

// Old viewport has to be replaced
scrollPane.setViewport(null);
scrollPane.setViewportView(zoomablePanel);

/ Anders

  

Das Problem, das ich habe, ist Herstellung   die JScrollPane Ansicht angezeigt werden, als ob es   ist immer noch die gleiche Position oben links auf   nachdem das Bild angepasst wurde.

Sorry, ich bin nicht sicher, was Sie fragen. Ich könnte in der Lage, eine Antwort zu geben, wenn Sie ein wenig klären.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top