2013-11-28 5 views
6

Ich habe Klasse Airplane genannt. Innerhalb dieser Klasse habe ich Variable img, die ein BufferedImage Typ ist. Was ist mehr, ich habe WorldMap bekam Klasse, die Funktion überschreibt paintComponent(Graphics g):Rotierendes Bild mit AffineTransform

@Override 
public void paintComponent(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.drawImage(mapa, 0, 0, getWidth(), getHeight(), null); 
    drawAirplanes(g2d); 
} 

Funktion drawAirplanes() sieht wie folgt aus:

private void drawAirplane(Graphics2D g){ 
    for(Samolot i: s){ 
     i.rotateAirplane(); 
     g.drawImage(i.getImg(),i.getX(),i.getY(),(int)i.getDim().getWidth(),(int)i.getDim().getHeight(), null); 
    } 
} 

Es ist einfach zu 1 müssen) drehen Flugzeug (BufferedImage innerhalb Flugzeug Objekt) 2) ziehen ihm.

Meine Airplane.rotateAirplane() Funktion sieht wie folgt aus:

public void rotateSamolot() { 
    AffineTransform tx = new AffineTransform(); 

    tx.translate(10,10); //10, 10 is height and width of img divide by 2 
    tx.rotate(Math.PI/2); 
    tx.translate(-10,-10); 

    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); 

    BufferedImage newImage =new BufferedImage(20, 20, img.getType()); //20, 20 is a height and width of img ofc 
    op.filter(img, newImage); 

     this.img = newImage; 
} 

OFC wenn im mein Programm nur mapa Objekt läuft gezogen wird. wenn im diese Spur zu löschen

this.img = newImage;

Ich habe zu OFC mein Flugzeug bekam aber nicht gedreht.

+0

Ich bin nicht sicher Wenn Sie die AffineTransform übersetzen möchten, sollten Sie stattdessen die Rotationspunkte mit der rotate-Methode angeben, die normalerweise der Mittelpunkt ist, aber das liegt an Ihnen. Ich würde auch nicht das Ergebnis der Rotation zurück auf das Master-Bild zuweisen, sonst Sie bis die Drehung compounding .... – MadProgrammer

+1

Ich "denke" im Grunde, was passiert, ist Ihr Bild wird "out of bounds" des verfügbaren Speicherplatzes gedreht ... – MadProgrammer

+1

Sie könnten sich dieses Beispiel ansehen (http://stackoverflow.com/questions/15779877/rotate-bufferedimage-inside-jpanel/15780090#15780090) – MadProgrammer

Antwort

12

Das Hauptproblem (das ich sehen kann) ist die Übersetzung des Graphics Zusammenhangs, der die Position versetzt, dass die Rotation stattfinden wird.

Ich denke "Rotation" standardmäßig an der oberen/linken Ecke des Graphics Context (wo es 0x0 Position ist, die Sie in etwas anderes übersetzt haben), könnte dies dazu führen, dass das Bild aus gedreht werden Rahmen (oder sichtbarer Bereich)

Sie sollten einen "Ankerpunkt" angeben, an dem die Rotation stattfindet, typischerweise ist das Zentrum meine persönliche Präferenz.

Das folgende Beispiel hat einfach ein Master-Bild (aufgrund von Größenbeschränkungen musste ich es skalieren, aber Sie brauchen das nicht). Ich benutze das dann, um eine "rotierte" Instanz zu generieren, die so dimensioniert ist, dass das Bild hinein passt. Das ist eine Menge Spaß mit trig - ich habe den Code irgendwo gestohlen, also ein Verdienst für diesen Entwickler.

In diesem Beispiel können Sie auf eine beliebige Stelle klicken, um den Drehpunkt zu ändern, damit Sie sehen können, was gerade passiert. Die Standardposition ist die Mitte der Scheibe ...

Spinning

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SampleRotation { 

    public static void main(String[] args) { 
     new SampleRotation(); 
    } 

    public SampleRotation() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       final RotationPane rotationPane = new RotationPane(); 
       final JSlider slider = new JSlider(0, 100); 
       slider.addChangeListener(new ChangeListener() { 
        @Override 
        public void stateChanged(ChangeEvent e) { 
         double angle = 720d * (slider.getValue()/100d); 
         rotationPane.setAngle(angle); 
        } 
       }); 
       slider.setValue(0); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(rotationPane); 
       frame.add(slider, BorderLayout.SOUTH); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class RotationPane extends JPanel { 

     private BufferedImage img; 
     private BufferedImage rotated; 
     private double angle; 
     private Point clickPoint; 

     public RotationPane() { 
      try { 
       img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/issue459.jpg")); 
       BufferedImage scaled = new BufferedImage(img.getWidth()/2, img.getHeight()/2, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2d = scaled.createGraphics(); 
       g2d.setTransform(AffineTransform.getScaleInstance(0.5d, 0.5d)); 
       g2d.drawImage(img, 0, 0, this); 
       g2d.dispose(); 
       img = scaled; 
       setAngle(0d); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 

      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mouseClicked(MouseEvent e) { 
        clickPoint = e.getPoint(); 
        repaint(); 
       } 

      }); 

     } 

     public void setAngle(double angle) { 
      this.angle = angle; 

      double rads = Math.toRadians(getAngle()); 
      double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads)); 
      int w = img.getWidth(); 
      int h = img.getHeight(); 
      int newWidth = (int) Math.floor(w * cos + h * sin); 
      int newHeight = (int) Math.floor(h * cos + w * sin); 

      rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); 
      Graphics2D g2d = rotated.createGraphics(); 
      AffineTransform at = new AffineTransform(); 
      at.translate((newWidth - w)/2, (newHeight - h)/2); 

      int x = clickPoint == null ? w/2 : clickPoint.x; 
      int y = clickPoint == null ? h/2 : clickPoint.y; 

      at.rotate(Math.toRadians(getAngle()), x, y); 
      g2d.setTransform(at); 
      g2d.drawImage(img, 0, 0, this); 
      g2d.setColor(Color.RED); 
      g2d.drawRect(0, 0, newWidth - 1, newHeight - 1); 
      g2d.dispose(); 

      repaint(); 
     } 

     public double getAngle() { 
      return angle; 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this)); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (rotated != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 

       int x = (getWidth() - rotated.getWidth())/2; 
       int y = (getHeight() - rotated.getHeight())/2; 
       g2d.drawImage(rotated, x, y, this); 

       g2d.setColor(Color.RED); 

       x = clickPoint == null ? getWidth()/2 : clickPoint.x; 
       y = clickPoint == null ? getHeight()/ 2 : clickPoint.y; 

       x -= 5; 
       y -= 5; 

       g2d.drawOval(x, y, 10, 10); 
       g2d.dispose(); 
      } 
     }   
    }  
} 
0

Dies ist, was für mich gearbeitet (ein bisschen von hier kopieren und dort):

public BufferedImage rotateImag (BufferedImage imag, int n) { //n rotation in gradians 

     double rotationRequired = Math.toRadians (n); 
     double locationX = imag.getWidth()/2; 
     double locationY = imag.getHeight()/2; 
     AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY); 
     AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);   
     BufferedImage newImage =new BufferedImage(imag.getWidth(), imag.getHeight(), imag.getType()); //20, 20 is a height and width of imag ofc 
     op.filter(imag, newImage); 

      //this.img = newImage; 
     return(newImage); 
    }