Image eines ImageIcons rotieren

Ja, hingeklatscht ist das Stichwort :smiley:

Wie gesagt, bei sowas bietet es sich an, die Transformationen, die man machen will (Translation, Rotation, Skalierung) getrennt zu betrachten und wie gewünscht zusammenzubauen, sonst kommt man schnell in die Koordinatensystem-Hölle (oder „noch schneller“).

Hier ist mal ein Beispiel… (hingeklatscht)

package bytewelt;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


public class BilderForumExtended
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
    
    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        TransformableImageComponent t = new TransformableImageComponent();
        
        MouseControl mouseControl = new MouseControl(t);
        t.addMouseListener(mouseControl);
        t.addMouseMotionListener(mouseControl);
        t.addMouseWheelListener(mouseControl);
        
        String path = "screenshotBoxAnimated.gif";
        ImageIcon imageIcon = new ImageIcon(path);
        t.setImageIcon(imageIcon);
        
        f.getContentPane().add(t);
        f.setSize(400,400);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    
    static class MouseControl extends MouseAdapter
    {
        private Point previousPoint = null;
        
        private final TransformableImageComponent transformableImageComponent;
        
        MouseControl(TransformableImageComponent transformableImageComponent)
        {
            this.transformableImageComponent = transformableImageComponent;
        }
        
        @Override
        public void mousePressed(MouseEvent e)
        {
            previousPoint = e.getPoint();
        }
        
        @Override
        public void mouseDragged(MouseEvent e)
        {
            int dx = e.getX() - previousPoint.x;
            int dy = e.getY() - previousPoint.y;
            if ((e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)
            {
                transformableImageComponent.translate(dx, dy);
            }
            else
            {
                double deltaAngleRad = dy / 100.0;
                transformableImageComponent.rotate(deltaAngleRad);
            }
            previousPoint = e.getPoint();
        }
        
        @Override
        public void mouseWheelMoved(MouseWheelEvent e)
        {
            double factor = 1.0 + e.getWheelRotation() * 0.1;
            transformableImageComponent.scale(factor);
        }
    }

    private static class TransformableImageComponent extends JComponent
    {
        private ImageIcon imageIcon;
        
        private Point translation = null;
        private double rotationAngleRad = 0.0;
        private double scale = 0.0;

        public void setImageIcon(ImageIcon imageIcon)
        {
            this.imageIcon = imageIcon;
            this.translation = null;
            validateTransform();
            repaint();
        }
        
        void setTranslation(Point p)
        {
            this.translation = new Point(p);
            repaint();
        }
        
        void translate(int dx, int dy)
        {
            if (translation == null)
            {
                translation = new Point();
            }
            translation.x += dx;
            translation.y += dy;
        }
        
        void setRotation(double rotationAngleRad)
        {
            this.rotationAngleRad = rotationAngleRad;
            repaint();
        }
        
        void rotate(double deltaAngleRad)
        {
            this.rotationAngleRad += deltaAngleRad;
            repaint();
        }
        
        void setScale(double scale)
        {
            this.scale = scale;
            repaint();
        }
        
        void scale(double factor)
        {
            scale *= factor;
            repaint();
        }
        
        private void validateTransform()
        {
            if (getWidth() <= 0 || getHeight() <= 0)
            {
                return;
            }
            if (imageIcon == null)
            {
                return;
            }
            if (translation != null)
            {
                return;
            }
            int iw = imageIcon.getIconWidth();
            int ih = imageIcon.getIconHeight();
            double factorW = (double) getWidth() / iw;
            double factorH = (double) getHeight() / ih;
            scale = Math.min(factorW, factorH);
            int x = (getWidth() - iw) / 2;
            int y = (getHeight() - iw) / 2;
            translation = new Point(x, y);
        }

        @Override
        protected void paintComponent(Graphics gr)
        {
            super.paintComponent(gr);
            if (imageIcon == null)
            {
                return;
            }
            Graphics2D g = (Graphics2D)gr;

            validateTransform();

            double centerX = imageIcon.getIconWidth() * 0.5; 
            double centerY = imageIcon.getIconHeight() * 0.5;

            AffineTransform at = new AffineTransform();
            System.out.println("trans "+translation);
            at.concatenate(AffineTransform.getTranslateInstance(translation.getX(), translation.getY()));
            at.concatenate(AffineTransform.getTranslateInstance(centerX, centerY));
            at.concatenate(AffineTransform.getRotateInstance(rotationAngleRad));
            at.concatenate(AffineTransform.getScaleInstance(scale, scale));
            at.concatenate(AffineTransform.getTranslateInstance(-centerX, -centerY));
            g.transform(at);
            g.drawImage(imageIcon.getImage(), 0, 0, this);
        }
    }
}

Bonuspunkte gäbe as natürlich, wenn man immer da hin zoomen würde, wo die Maus gerade ist, aber das wäre auch nicht sooo schwierig…