Поворот изображения с помощью AffineTransform

У меня есть class под названием « Airplane . Внутри этого classа у меня есть переменная img которая является типом BufferedImage . Более того, у меня есть class WorldMap который переопределяет функцию paintComponent(Graphics g) :

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

Функция drawAirplanes() выглядит так:

 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); } } 

Это просто нужно: 1) вращать самолет (BufferedImage внутри объекта самолета) 2) привлечь его.

Моя функция Airplane.rotateAirplane () выглядит так:

  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, когда im запускает мою программу, рисуется только объект mapa . когда я удаляю эту полосу

this.img = newImage;

Я тоже получил свой самолет, но не повернулся.

Основная проблема (я могу видеть) – это перевод контекста Graphics который смещается в положение, в котором будет происходить поворот.

Я думаю, что rotation по умолчанию происходит в верхнем / левом углу контекста Graphics (где это позиция 0x0, которую вы перевели на что-то еще), это может привести к тому, что изображение будет повернуто из кадра (или просмотра площадь)

Вы должны указать точку привязки, где происходит поворот, как правило, центр – это мое личное предпочтение.

Следующий пример просто имеет основное изображение (из-за ограничений по размеру я должен был масштабировать его, но вам может и не понадобиться). Затем я использую это для создания «повернутого» экземпляра, размер которого позволяет разместить изображение в пределах. Это очень весело с помощью триггера – я украл код откуда-то, поэтому кредит для этого разработчика.

В этом примере вы можете щелкнуть любое место, и оно изменит ось поворота, чтобы вы могли видеть, что происходит. По умолчанию это центр области …

прядильный

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

Это то, что сработало для меня (вид копирования отсюда и там):

 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); } 
  • Проблемы, связанные с функцией JPanel: paintcomponent ()
  • Как отображать слабый серый «текст-призрак» в JTextField?
  • как создать собственный файл со значком, который наследует значок JFrame, который я установил, в java и моем собственном файле используйте FileOutputStream и ObjectOutputStream
  • Добавляет ли JLabel в JPanel «скрыть» JPanel?
  • Как изменить цвет JSplitPane
  • Как сделать JTable недоступным для редактирования
  • Как получить значение из JTextField в Java Swing?
  • Добавьте JLabel с изображением в JList, чтобы показать все изображения
  • Как обрабатывать события с клавиатуры и мыши в полноэкранном эксклюзивном режиме в java?
  • Удалить контейнер верхнего уровня во время выполнения
  • Алгоритм цветового затухания?
  • Давайте будем гением компьютера.