如何在 java 中一起旋转多个图形形状而不改变它们在框架上的位置或它们相对于彼此的位置?

How can I rotate multiple graphics shapes together in java without changing their position on the frame or their position relative to eachother?

我一起使用了几个 java.awt.Rectangle、java.awt.Polygon 和 java.awt.geom.Ellipse2D 形状,我想将它们相互旋转,并且我还想让它们保持它们的位置JFrame。当我使用 g2D.rotate(Math.toRadians(rotation)) 时,形状在 JFrame 上移动并且它们不再靠近在一起。我怎样才能使所有形状保持它们相对于彼此的位置以及它们在 JFrame 上的位置?提前谢谢你。

记住这一点非常重要,转换是复合的。因此,您不能简单地将新的旋转应用到每个对象的 Graphics 上下文,相反,您需要重置转换之间的状态

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Shape> shapes = new ArrayList<>(4);

        private double angle = 0;

        public TestPane() {
            shapes.add(new Rectangle2D.Double(50, 50, 100, 100));
            shapes.add(new Rectangle2D.Double(250, 50, 100, 100));
            shapes.add(new Rectangle2D.Double(50, 250, 100, 100));
            shapes.add(new Rectangle2D.Double(250, 250, 100, 100));

            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angle += 1;
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Shape shape : shapes) {
                Graphics2D g2d = (Graphics2D) g.create();
                Rectangle bounds = shape.getBounds();
                int midx = bounds.x + (bounds.width / 2);
                int midy = bounds.y + (bounds.height / 2);
                g2d.setTransform(AffineTransform.getRotateInstance(Math.toRadians(angle), midx, midy));
                g2d.draw(shape);
                g2d.dispose();
            }
        }

    }
}

也可以直接变换形状,例如...

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g.create();
    for (Shape shape : shapes) {
        Rectangle bounds = shape.getBounds();
        int midx = bounds.x + (bounds.width / 2);
        int midy = bounds.y + (bounds.height / 2);
        Path2D.Double rotatedShape = new Path2D.Double(shape, AffineTransform.getRotateInstance(Math.toRadians(angle), midx, midy));
        g2d.draw(rotatedShape);
    }
    g2d.dispose();
}

如果您希望能够一起旋转形状并保持它们在 JFrame 上的位置,我建议您使用使用 x 和 y 坐标旋转的 g2D.rotate 形式。你应该制作一个标准的 x 和 y 坐标来绘制每个形状的位置,这样当你使用这些标准的 x 和 y 坐标旋转时,所有的形状都会一起旋转。它可能看起来像这样:

//  imports
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Container;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;  
import javax.swing.JComponent;

public class GraphicsRotate extends JComponent implements ActionListener {

    //  JFrame and Container
    JFrame frame = new JFrame("Graphics Rotate");
    Container container = frame.getContentPane();
    public int standardX = 100;
    public int standardY = 100;
    public int rotation = 0;

    public static void main(String[] args) {
        GraphicsRotate graphicsRotate = new GraphicsRotate();
        graphicsRotate.setup();

    }

    public void setup() {
        container.setBackground(Color.BLACK);
        container.add(this);

        KeyListener kl = new KeyListener() {
            public void keyPressed(KeyEvent e) {
               int code = e.getKeyCode();
               if (code == KeyEvent.VK_LEFT) {
                   rotation -= 10;
                   repaint();
               }
               if (code == KeyEvent.VK_RIGHT) {
                   rotation += 10;
                   repaint();
               }
            }

            public void keyReleased(KeyEvent e) {

            }

            public void keyTyped(KeyEvent e) {

            }
        };

        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addKeyListener(kl);
        frame.setFocusable(true);
        frame.requestFocus();
        frame.setVisible(true);
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g.setColor(Color.GREEN);
        g2.rotate(Math.toRadians(rotation), standardX, standardY);
        Rectangle rect = new Rectangle(standardX + 10, standardY + 10, 5, 
5);
        Ellipse2D ellipse = new Ellipse2D.Double(standardX + 13, standardY 
+ 5, 10, 10);
        g2.fill(ellipse);
        g2.fill(rect);

    }

    @Override
    public void actionPerformed(ActionEvent e) {

    } 

}

这可以在更大的规模上实现,如果您希望形状围绕您用它们制作的更大形状的中心旋转,那么您可以进行必要的计算以找出中心和做类似 g2.rotate(Math.toRadians(旋转), standardX + middleX, standardY + middleY).

我希望这能回答您的问题。