Java AWT旋转球

Java AWT旋转球,java,swing,trigonometry,Java,Swing,Trigonometry,哦,天哪,三角学太难了!我需要一些帮助,这是一个简单的程序,应该是围绕屏幕中心旋转一个球。。。这是我的密码: import java.awt.*; import javax.swing.*; public class Window { private int x; private int y; private int R = 30; private double alpha = 0; private final int SPEED = 1; private final Color COL

哦,天哪,三角学太难了!我需要一些帮助,这是一个简单的程序,应该是围绕屏幕中心旋转一个球。。。这是我的密码:

import java.awt.*;

import javax.swing.*;


public class Window {
private int x;
private int y;
private int R = 30;
private double alpha = 0;

private final int SPEED = 1;
private final Color COLOR = Color.red;

public static void main(String[] args) {    
    new Window().buildWindow();
}

public void buildWindow() {
    JFrame frame = new JFrame("Rotation");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800,600);
    frame.setVisible(true);
    frame.add(new DrawPanel());
    while(true) {
        try {
            Thread.sleep(60);
            alpha += SPEED;
            frame.repaint();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

@SuppressWarnings("serial")
class DrawPanel extends JPanel {


    @Override
    public void paintComponent(Graphics g) {
        g.setColor(Color.blue);
        Font font = new Font("Arial",Font.PLAIN,12);
        g.setFont(font);
        g.drawString(String.format("Angle: %.2f ", alpha), 0, 12);

        g.setColor(Color.black);
        g.drawLine(this.getWidth()/2,0, this.getWidth()/2, this.getHeight());
        g.drawLine(0, this.getHeight()/2, this.getWidth(), this.getHeight()/2);

        x = (int) ((this.getWidth() / 2 - R / 2 ) + Math.round((R + 20) * Math.sin(alpha)));
        y = (int) ((this.getHeight() / 2 - R / 2 ) + Math.round((R + 20) * Math.cos(alpha)));

        g.setColor(COLOR);
        g.fillOval(x, y, R, R);
    }
}
}
这段代码看起来很有效,但我已经将角度[alpha]信息打印到了屏幕上。当我注释掉
alpha+=SPEED
并手动输入角度时,它看起来不工作。屏幕上的角度与该角度
alpha
不对应。
所以我需要建议。我应该换什么?我的三角学错了吗?等等

这里需要注意三件事:

  • 我假设您的
    alpha
    变量以度为单位,因为您在每个步骤中添加了20。然而,
    Math.sin()
    Math.cos()
    方法需要以弧度为单位的角度
  • 通常在“3点钟”位置表示0度(或0拉德)。为此,您需要切换
    sin
    cos
    调用
  • y
    等式中的符号反转,以说明
    y
    坐标从屏幕顶部开始向下增加的事实
  • 通过这些修改,您的代码将按预期工作:

    double rads = (alpha * Math.PI) / 180F;
    x = (int) ((this.getWidth() / 2 - R / 2 ) + Math.round((R + 20) * Math.cos(rads)));
    y = (int) ((this.getHeight() / 2 - R / 2 ) - Math.round((R + 20) * Math.sin(rads)));
    

    这是一个典型的EDT(事件调度线程)阻塞问题,由
    Thread.sleep()
    调用引起。有关避免在EDT中使用
    Thread.sleep()
    的更多信息,请参阅。正如这里所建议的,使用a来执行定期更新。这是错误的。这里没有EDT阻塞问题。对
    Thread.sleep()
    的调用在主线程中,而不是在链接问题中的EDT中。你是对的。这甚至是最糟糕的。EDT中不进行帧创建和
    repaint()
    调用。OP应该只重新绘制
    DrawPanel
    对象,而不是整个帧。顺便说一句,在任何情况下,调用
    Thread.sleep()
    的循环都不是一个好的做法。OP应按照建议使用摆动计时器@Grodriguezn需要在EDT中创建帧或调用
    repaint()
    。但无论如何,这与原始海报的问题无关。我的评论是建议良好做法,而不是直接回答。当然,如果我复制并粘贴此代码,它将工作,因此显然没有必要在EDT中创建帧。但是,从
    SwingUtilities.invokeLater(…)
    开始的数千个示例不会错。这是从笛卡尔坐标转换到极坐标的标准方法,0度角表示在“3点钟”位置()好的,还有一件事,当角度达到360度时,我是否需要将角度重置回0?(因为整圆是360度)?无需重置角度。大于360º的值也是有效角度。