Java 使用图形进行旋转2d

Java 使用图形进行旋转2d,java,swing,rotation,keylistener,graphics2d,Java,Swing,Rotation,Keylistener,Graphics2d,我目前正在试验Graphics2D和KeyListener,我目前正在测试旋转对象(在本例中为五角大楼)。现在,它在旋转的意义上工作,除了每次按下VK_RIGHT或VK_LEFT时,它应该旋转1弧度 然而,目前它只在第一次按键时这样做。从那时起,它创建了一个旋转1,2,3,4,5。。。以此类推,每次弧度(第n个按键旋转n个弧度),而不是每个按键仅旋转1个弧度 创建JFrame: import javax.swing.JFrame; public class Main {

我目前正在试验Graphics2D和KeyListener,我目前正在测试旋转对象(在本例中为五角大楼)。现在,它在旋转的意义上工作,除了每次按下VK_RIGHT或VK_LEFT时,它应该旋转1弧度

然而,目前它只在第一次按键时这样做。从那时起,它创建了一个旋转1,2,3,4,5。。。以此类推,每次弧度(第n个按键旋转n个弧度),而不是每个按键仅旋转1个弧度

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

    }
旋转六角类:

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

}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Polygon;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入javax.swing.JPanel;
公共类RotatingHexagon扩展JPanel实现KeyListener{
私有多边形多边形;
私有int[]xpoints={0,-10,-7,7,10};
私有int[]ypoints={-10,-2,10,10,-2};
私有整数旋转=0;
公共轮调hexagon(){
设置首选尺寸(新尺寸(800600));
设置聚焦(真);
requestFocus();
}
公共void init(){
多边形=新多边形(X点、Y点、X点长度);
addKeyListener(此);
}
公共空间涂料(图g){
init();
Graphics2D g2d=(Graphics2D)g;
int width=getSize().width;
int height=getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0,0,宽度,高度);
g2d.setColor(Color.WHITE);
g2d.拉丝(旋转+弧度,10,20);
g2d.平移(宽度/2,高度/2);
g2d.比例(20,20);
旋转(数学托拉迪安旋转);
g2d.setColor(新颜色(2551000));
g2d.填充(poly);
g2d.setColor(Color.WHITE);
g2d.draw(poly);
}
按下公共无效键(KeyEvent k){
开关(k.getKeyCode()){
case KeyEvent.VK_左:
旋转--;
如果(旋转<0)旋转=359;
重新油漆();
打破
case KeyEvent.VK_RIGHT:
旋转++;
如果(旋转>360)旋转=0;
重新油漆();
打破
}
}
public void keyReleased(KeyEvent k){}
public void keyTyped(KeyEvent k){}
}
我真的不知道为什么它不只是每次旋转1弧度,所以非常感谢您的帮助。
谢谢。

原因是反复调用paint()方法中的init()函数。因此,KeyListener被多次添加,导致它被多次调用,每次按下该键时计数器都会增加更多

将其移动到构造函数:

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

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

Andy

您可能应该使用持久仿射变换来进行旋转。它们的力量要大得多

我还看到了代码中的一些问题,您在每帧调用init方法-这可能是每秒60次。在这里,您将为每个帧添加一个新的keylistener。您还将创建一个新多边形,这将降低性能

我对您的代码做了一些更改,并以仿射变换为例。看看这是否有用

package com.joey.testing;

import java.awt.BorderLayout;
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 java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class AffineTransformTest 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;
    AffineTransform transform;
    AffineTransform rotationTransform;
    AffineTransform translateTransform;

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

        //Do Init here - no point in creating new polygon each frame.
        //It also adds the key listener each time
        init();
        updateTransforms();
    }

    public void init() {
        poly = new Polygon(xpoints, ypoints, xpoints.length);
        transform = new AffineTransform();
        rotationTransform = new AffineTransform();
        translateTransform = new AffineTransform();
        addKeyListener(this);
    }

    //Use Paint Compoent
    @Override
    public void paintComponent(Graphics g) {
        //Always call super to clear the screen
        super.paintComponent(g);
        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);


        //Store old transform so we can apply it
        AffineTransform old = g2d.getTransform();
        //Add Transform and move polygon
        g2d.setTransform(transform);
        g2d.setColor(new Color(255, 100, 100));
        g2d.fill(poly);
        g2d.setColor(Color.WHITE);
        g2d.draw(poly);
        g2d.setTransform(old);
    }

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

    public void updateTransforms(){
        //Resets transform to rotation
        rotationTransform.setToRotation(Math.toRadians(rotation));
        translateTransform.setToTranslation(getWidth()/2, getHeight()/2);

        //Chain the transforms (Note order matters)
        transform.setToIdentity();
        transform.concatenate(translateTransform);
        transform.concatenate(rotationTransform);
    }

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


    public static void main(String input[]){
        JFrame f= new JFrame("AffineTransform");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(100, 100);
        f.setResizable(true);
        f.getContentPane().setLayout(new BorderLayout());
        f.getContentPane().add(new AffineTransformTest());
        f.show();

    }
}
package com.joey.testing;
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Polygon;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.awt.geom.AffineTransform;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类AffineTransformTest扩展JPanel实现KeyListener{
私有多边形多边形;
私有int[]xpoints={0,-10,-7,7,10};
私有int[]ypoints={-10,-2,10,10,-2};
私有整数旋转=0;
仿射变换;
仿射变换;
仿射变换;
公共仿射TransformTest(){
设置首选尺寸(新尺寸(800600));
设置聚焦(真);
requestFocus();
//DoInit here-在每个帧中创建新多边形没有意义。
//它还每次添加密钥侦听器
init();
updateTransforms();
}
公共void init(){
多边形=新多边形(X点、Y点、X点长度);
transform=新仿射变换();
rotationTransform=新仿射变换();
translateTransform=新仿射Transform();
addKeyListener(此);
}
//使用油漆成分
@凌驾
公共组件(图形g){
//始终呼叫super以清除屏幕
超级组件(g);
Graphics2D g2d=(Graphics2D)g;
int width=getSize().width;
int height=getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0,0,宽度,高度);
g2d.setColor(Color.WHITE);
g2d.拉丝(旋转+弧度,10,20);
//存储旧的转换以便我们可以应用它
仿射变换old=g2d.getTransform();
//添加变换并移动多边形
g2d.setTransform(transform);
g2d.setColor(新颜色(2551000));
g2d.填充(poly);
g2d.setColor(Color.WHITE);
g2d.draw(poly);
g2d.setTransform(旧);
}
按下公共无效键(KeyEvent k){
开关(k.getKeyCode()){
case KeyEvent.VK_左:
旋转--;
如果(旋转<0)旋转=359;
重新油漆();
打破
case KeyEvent.VK_RIGHT:
旋转++;
如果(旋转>360)旋转=0;
重新油漆();
打破
}
updateTransforms();
}
public void updateTransforms(){
//将变换重置为旋转
旋转变换.设置旋转(数学.旋转半径(旋转));
setToTranslation(getWidth()/2,getHeight()/2);
//柴