2013-11-28 49 views
1

哦,男孩,三角是如此的辛苦!我還挺需要一些幫助,這是應該繞屏幕的中心球一個簡單的程序...這裏是我的代碼:Java AWT旋轉球

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+=SPEED並手動輸入角度時,它看起來不像是在工作。屏幕上的角度與該角度不對應alpha。 所以我需要建議。我應該改變什麼?我的三角學錯了嗎?等等......

+1

這是一個經典的EDT(Event Dispatching Thread)阻塞問題,由Thread.sleep()調用引起。看看** [這個問題](http://stackoverflow.com/questions/20219885/forcing-a-gui-update-inside-of-a-thread-jslider-updates/20220319#20220319)** for有關避免在EDT中使用'Thread.sleep()'的更多信息。如上所示,使用** [Swing Timer](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)**執行定期更新。 – dic19

+0

這是錯誤的。這裏沒有EDT阻塞問題。對Thread.sleep()的調用位於主線程中,而不是像在鏈接問題中那樣位於EDT中。 – Grodriguez

+0

你說得對。這甚至是最糟糕的。在EDT中不創建幀創建和repaint()調用。並且OP應該只重畫'DrawPanel'對象而不是整個框架BTW。無論如何,調用Thread.sleep()的循環根本不是一個好習慣。 OP應該按照建議使用擺動計時器。 @Grodriguez – dic19

回答

2

三樣東西這裏要注意:

  1. 我假設你alpha變量是度,因爲你是在每一步加20。然而,Math.sin()Math.cos()方法期望以弧度表示角度。
  2. 通常0度(或0拉德)表示在「3點鐘」的位置。爲此,您需要切換sincos調用。
  3. 反向的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))); 
+0

你是對的。我測試過它,它的工作原理:) – kai

+0

這是從笛卡爾轉換爲極座標的標準方式,零度角表示在「3點鐘」位置(http://en.wikipedia.org/wiki/ Polar_coordinate_system) – Grodriguez

+0

還有一件事,當360達到360度時需要將角度重置爲0(因爲整圓是360度)? –