Rotate a Java Graphics2D Rectangle?

91,582

Solution 1

For images you have to use drawImage method of Graphics2D with the relative AffineTransform.

For shape you can rotate Graphics2D itself:

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.setColor(Color.WHITE);
    Rectangle rect2 = new Rectangle(100, 100, 20, 20);

    g2d.rotate(Math.toRadians(45));
    g2d.draw(rect2);
    g2d.fill(rect2);
}

And btw, you should override paintComponent method instead of paint.

Citing JComponent's API:

Invoked by Swing to draw components. Applications should not invoke paint directly, but should instead use the repaint method to schedule the component for redrawing.

This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren. They're called in the order listed to ensure that children appear on top of component itself. Generally speaking, the component and its children should not paint in the insets area allocated to the border. Subclasses can just override this method, as always. A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent.

Remember also than when you perform an affine transformation, like a rotation, the object is implicitly rotated around the axis origin. So if your intent is to rotate it around an arbitrary point, you should before translating it back to the origin, rotate it, and then re-traslating it to the desired point.

Solution 2

public void draw(Graphics2D g) {
    Graphics2D gg = (Graphics2D) g.create();
    gg.rotate(angle, rect.x + rect.width/2, rect.y + rect.height/2);
    gg.drawRect(rect.x, rect.y, rect.width, rect.height);
    gg.dispose();

    gg = (Graphics2D) g.create();
    ... other stuff
}

Graphics.create() and Graphics.dispose() allow you to save the current transformation parameters (as well as current font, stroke, paint, etc), and to restore them later. It is the equivalent of glPushMatrix() and glPopMatrix() in OpenGL.

You can also apply an inverse rotation once you drew the rectangle to revert the transformation matrix back to its initial state. However, floating point approximations during substractions may lead to a false result.

Solution 3

Another way is by using Path2D, with it you can rotate the path only and not the entire graphics object:

Rectangle r = new Rectangle(x, y, width, height);
Path2D.Double path = new Path2D.Double();
path.append(r, false);

AffineTransform t = new AffineTransform();
t.rotate(angle);
path.transform(t);
g2.draw(path);
Share:
91,582
chrypthic
Author by

chrypthic

Updated on July 09, 2022

Comments

  • chrypthic
    chrypthic almost 2 years

    I have searched everywhere and I just cant find the answer.
    How do I rotate a Rectangle in java?

    Here is some of my code:

    package net.chrypthic.Space;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Space extends JPanel implements ActionListener{
        Timer time;
        public Space()
        {
            setVisible(true);
            setFocusable(true);
            addMouseMotionListener(new ML());
            addMouseListener(new ML());
            addKeyListener(new AL());
            time=new Timer(5, this);
            time.start();
        }
        public void paint(Graphics g)
        {
            super.paint(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setColor(Color.WHITE);
            Rectangle rect2 = new Rectangle(100, 100, 20, 20);
    
            g2d.draw(rect2);
            g2d.fill(rect2);
        }
        public void actionPerformed(ActionEvent ae) {
            repaint();
        }
        public class AL extends KeyAdapter
        {
            public void keyPressed(KeyEvent e) {
            }
    
            public void keyReleased(KeyEvent e) {
            }
        }
        public class ML extends MouseAdapter
        {
            public void mouseMoved(MouseEvent e) {
            }
    
            public void mousePressed(MouseEvent e){
            }
        }
    }
    

    I tried g2d.rotate(100D); but it didnt work. Thanks in advance.

    Here's my edited code:

    package net.chrypthic.Space;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Space extends JPanel implements ActionListener{
        Timer time;
        public Space()
        {
            setVisible(true);
            setFocusable(true);
            setSize(640, 480);
            setBackground(Color.BLACK);
            time=new Timer(5, this);
            time.start();
        }
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            Rectangle rect1 = new Rectangle(100, 100, 20, 20);
            g2d.setColor(Color.WHITE);
            g2d.translate(rect1.x+(rect1.width/2), rect1.y+(rect1.height/2));
            g2d.rotate(Math.toRadians(90));
            g2d.draw(rect1);
            g2d.fill(rect1);
        }
        public void actionPerformed(ActionEvent e) 
        {
            repaint();
        }
    }
    
  • chrypthic
    chrypthic over 12 years
    Thanks ill try it, what is better about paintComponent?
  • chrypthic
    chrypthic over 12 years
    K, i tried it. Now my rectangle is wedged in the left corner although I set the X position to 100. Why is this happening? (screenie: cl.ly/AM8c)
  • Heisenbug
    Heisenbug over 12 years
    draw method doesn't exist for JComponent
  • chrypthic
    chrypthic over 12 years
    "Remember also than when you perform an affine transformation, like a rotation, the object is implicitly rotated around the axis origin. So if your intent is to rotate it around an arbitrary point, you should before translating it back to the origin, rotate it, and then re-traslating it to the desired point." How'd I do that?
  • Heisenbug
    Heisenbug over 12 years
    you are drawing a square : new Rectangle(100, 100, 20, 20); It's located at 100,100. If you define your rectangle this way: new Rectangle(-10, -10, 20, 20); then perform the rotation and then g2d.translate(100,100); you should obtain the desired result.
  • chrypthic
    chrypthic over 12 years
    Thanks. I have translated it, now when I change the X or the Y and my rotation is 90 (its pointless but a test), it moves down instead of right or down. Why? Is there a way around this?
  • Heisenbug
    Heisenbug over 12 years
    try to post the modified code, but I won't do a complete tutorial on affine transforms. It's a subject that it's intuitive at a first approach. There are many tutorials on the net, search for them and start following some examples.
  • Aurelien Ribon
    Aurelien Ribon over 12 years
    Of course, I expect the op to know how to draw on a JPanel, this is just a code snippet :)
  • chrypthic
    chrypthic over 12 years
    I have edited my post above. And thanks, i will look at some affine transforms tutorials. Thanks for all your help :D
  • trashgod
    trashgod over 12 years
    +1 See also this related example.
  • trashgod
    trashgod over 12 years
    +1 for the other rotate().
  • atw
    atw about 7 years
    Finally a SO person who knows what they are talking about, thank you. +1