Search code examples
javaswingrotationkeylistenergraphics2d

Rotation with Graphics2D


I am currently experimenting with the Graphics2D and the KeyListener, and I am currently testing out rotating objects (in this case a pentagon). Now, it's working in the sense that it rotates, except it is supposed to rotate by 1 radian each time VK_RIGHT or VK_LEFT are pressed.

However, currently it does that for the first key press only. From then on, it creates a pattern of rotating it by 1, 2, 3, 4, 5... and so on radians each time (the nth keypress rotates it by nth radians) instead of just 1 radian per keypress.

Creating the JFrame:

import javax.swing.JFrame;


    public class Main {

        public Main() {
            JFrame window = new JFrame("Rotating Hexagons");
            window.setSize(800,600);
            window.setLocationRelativeTo(null);
            window.setResizable(false);
            window.setContentPane(new RotatingHexagon());
            window.pack();
            window.setVisible(true);
        }

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

    }

RotatingHexagon Class:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;


public class RotatingHexagon extends JPanel implements KeyListener {

    private Polygon poly;

    private int[] xpoints = { 0, -10, -7, 7, 10 };
    private int[] ypoints = { -10, -2, 10, 10, -2 };

    private int rotation = 0;

    public RotatingHexagon() {
        setPreferredSize(new Dimension(800,600));
        setFocusable(true);
        requestFocus();
    }

    public void init() {
        poly = new Polygon(xpoints, ypoints, xpoints.length);

        addKeyListener(this);
    }

    public void paint(Graphics g) {
        init();

        Graphics2D g2d = (Graphics2D) g;

        int width = getSize().width;
        int height = getSize().height;

        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, width, height);

        g2d.setColor(Color.WHITE);
        g2d.drawString(rotation + " radians", 10, 20);

        g2d.translate(width / 2, height / 2);
        g2d.scale(20, 20);
        g2d.rotate(Math.toRadians(rotation));

        g2d.setColor(new Color(255, 100, 100));
        g2d.fill(poly);
        g2d.setColor(Color.WHITE);
        g2d.draw(poly);
    }

    public void keyPressed(KeyEvent k) {
        switch(k.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            rotation--;
            if (rotation < 0) rotation = 359;
            repaint();
            break;
        case KeyEvent.VK_RIGHT:
            rotation++;
            if (rotation > 360) rotation = 0;
            repaint();
            break;
        }
    }

    public void keyReleased(KeyEvent k) {}
    public void keyTyped(KeyEvent k) {}

}

I really don't have any idea why it isn't just rotating 1 radian each time, so any help is appreciated. Thanks.


Solution

  • the reason is calling the init() function in the paint() method again and again. So the KeyListener is added multiple times, causing that it is called multiple times, incrementing your counter more every time you press the key.

    Move it to the constructor:

    public RotatingHexagon() {
        setPreferredSize(new Dimension(800,600));
        setFocusable(true);
        requestFocus();
        addKeyListener(this);
    }
    
    public void init() {
        poly = new Polygon(xpoints, ypoints, xpoints.length);        
    }
    

    Andy