Home > other >  How can I rotate multiple graphics shapes together in java without changing their position on the fr
How can I rotate multiple graphics shapes together in java without changing their position on the fr

Time:04-28

I have used several java.awt.Rectangle, java.awt.Polygon, and java.awt.geom.Ellipse2D shapes together and I want to rotate them with eachother and I also want to have them keep their location on the JFrame. When I use g2D.rotate(Math.toRadians(rotation)), the shapes move on the JFrame and they are no longer close together. How can I make it so that all of the shapes keep their position relative to eachother and their position on the JFrame? Thank you in advance.

CodePudding user response:

If you want to be able to rotate the shapes together and keep their position on the JFrame I would recommend that you use the form of g2D.rotate that uses x and y coordinates to rotate with. You should make a standard x and y coordinate to draw each shapes position from so that when you use these standard x and y coordinates to rotate from all of the shapes will rotate together. It would probably look something like this:

//  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) {

    } 

}

This could be implemented on a much larger scale, and if you wanted the shapes to rotate around the center of the larger shape that you have made with them, then you could do the necessary calculations to figure out the center and do something like g2.rotate(Math.toRadians(rotation), standardX middleX, standardY middleY).

I hope that this answered your question.

CodePudding user response:

It's really important to remember, transformations are compounding. So you can't simply apply a new rotation to the Graphics context for each object, instead, you need to reset the state between transformations

enter image description here

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

    }
}

You could also transform the shape directly, for example...

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