4

I am trying to draw a rectangle in JPanel that would translate and then rotate itself to mimic the movement of a car. I have been able to make the rectangle translate and rotate, however it rotates around the origin of (0,0). I'm very pleased that I was able to have the rectangle move and rotate as I am very new to Java GUI, but I can not seem to get how to have the rectangle rotate around itself, because I experimented more with it, and when I initialized the rectangle and rotate it 45 degrees it's position was changed, which I would assume is the transform matrix that is appended from the rotate method.

I checked through the site on how would I solve this, however I only found how to rotate a rectangle and not on how to rotate and move like the movement of a simulated car. I would presume it is concerning about its transform matrix, but I'm only speculating. So my question is how would I be able to have the rectangle be able to rotate and move around itself and not against a point in JPanel.

Here's the code that I have come up so far:

public class Draw extends JPanel implements ActionListener {


private int x = 100;
private int y = 100;
private double theta = Math.PI;

Rectangle rec = new Rectangle(x,y,25,25);

Timer timer = new Timer(25,this);

Draw(){
    setBackground(Color.black);
    timer.start();
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;     
    g2d.setColor(Color.white);
    rec.x = 100;
    rec.y = 100;
    g2d.rotate(theta);
    g2d.draw(rec);
    g2d.fill(rec);

}

public void actionPerformed(ActionEvent e) {
    x = (int) (x + (Math.cos(theta))*1);
    y = (int) (y + (Math.sin(theta))*1);
    theta = theta - (5*Math.PI/180);
    repaint();
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
John Cava
  • 43
  • 1
  • 5

2 Answers2

7

One of two approaches are commonly used:

  • Rotate the graphics context around the center (x, y) of the Shape, as shown here.

    rotate(double theta, double x, double y)
    
  • Translate to the origin, rotate and translate back, as shown here.

    g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
    g2d.rotate(theta);
    g2d.translate(-image.getWidth(null) / 2, -image.getHeight(null) / 2);
    

Note the apparent reverse order of concatenation in the second example.

Addendum: Looking more closely at your example, the following change rotates the Rectangle around the panel's center.

g2d.rotate(theta, getWidth() / 2, getHeight() / 2);

Also, use the @Override annotation, and give your panel a reasonable preferred size:

@Override
public Dimension getPreferredSize() {
    return new Dimension(640, 480);
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    Thanks for the answer, the first approach that you stated was the one I needed. I didn't realize that the rotate method had the parameters to position its coordinates, so I put the position of the rectangle as the parameters and it works great. Thanks again. – John Cava Jan 01 '13 at 06:59
  • 1
    +1 very nice. @user1914793 see also this [example](http://stackoverflow.com/questions/13519449/rotate-rectangle-and-move-it-in-sin-wave-help-using-graphics2d/13519588#13519588) which uses `AffineTransform#rotate(..)` and `AffineTransform#createTransformedShape():` – David Kroukamp Jan 01 '13 at 12:12
1

Use affine transform to rotate the rectangle and convert it into the rotated polynomial. Check the code below:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.white);
    /* rotate rectnagle around rec.x and rec.y */
    AffineTransform at = AffineTransform.getRotateInstance(theta, 
        rec.x, rec.y);
    /* create the plunomial */
    Polygon p = new Polygon();
    /* path interator of the affine transformed polynomial */
    PathIterator i = rec.getPathIterator(at);
    while (!i.isDone()) {
        double[] points = new double[2];
        i.currentSegment(points);
        p.addPoint((int) points[0], (int) points[1]);

        i.next();
    }
    g2d.fill(p);
}
Shivam
  • 2,134
  • 1
  • 18
  • 28
  • There's no need to iterate the path of a `Shape`; use `createTransformedShape()` instead, as shown [here](http://stackoverflow.com/a/5594424/230513). – trashgod Jan 01 '13 at 06:08