2016-11-13 141 views
-1

該代碼旨在繪製一個矩形,該矩形一次圍繞畫布中心移動一圈。我公司目前擁有的代碼是如何繪製圍繞畫布中心的圓圈移動矩形?

import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Rectangle2D; 
import javax.swing.Timer; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 

public class Q3_Circular extends JComponent { 

protected int degree = 0; 
protected double xStart; 
protected double yStart; 
protected Timer timer; 


public Q3_Circular() { 
    timer = new Timer(1000, new TimerCallback()); //creates new times that refreshes every 100 ms, and called the TimerCallback class 
    timer.start(); 
} 

protected class TimerCallback implements ActionListener { 

    public void actionPerformed(ActionEvent e) { 

     if (degree < (2 * Math.PI)){ 
      xStart = getWidth()/2 * Math.cos(degree+1); 
      yStart = getHeight()/2 * Math.sin(degree+1); 
      degree+= 1; 
      repaint(); 
     } 
     else { 
      degree += 0; 
      repaint(); 
     } 

    } 
} 


public static void main(String[] args) { 
    JFrame frame = new JFrame("AnimatedSquare"); 
    Q3_Circular canvas = new Q3_Circular(); 
    frame.add(canvas); 
    frame.setSize(300, 300); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    frame.setVisible(true); 
} 

public void paintComponent(Graphics g){ 
    xStart = (double)(getWidth())/2.0 * Math.cos(degree); 
    yStart = (double)(getHeight())/2.0 * Math.sin(degree); 

    Graphics2D g2 = (Graphics2D) g; 
    g2.draw(new Rectangle2D.Double(xStart,yStart, 25,25)); 
    repaint(); 
} 
} 

此代碼出現非常迅速地繪製矩形圍繞點(0,0)。我不確定代碼出錯的地方。

+1

您需要知道'Math#cos'和'Math#sin'中的'degree'參數假設爲* Radian *而非Degrees。此外,您應該知道,對於某些輸入,「sin」和「cos」函數的輸出可以是** Negative **。所以你的'xStart'和'yStart'被計算爲負值,然後在你的幀之外繪製。另外,當您在'paintComponent'方法中計算'xStart'和'yStart'時,您將忽略'actionPerformed'方法中的計算。詢問任何問題,如果這些提示沒有幫助。 – STaefi

+0

順便說一句,雖然它沒有回答你的問題,但可能它可以簡化你的代碼。在Graphics2D中,您可以使用仿射變換進行旋轉。他們基本上會讓你擺脫三角函數。請閱讀此處:http://docs.oracle.com/javase/tutorial/2d/advanced/transforming.html –

+0

謝謝,這非常有幫助。我仍然遇到的唯一問題是它圍繞點0,0圍繞點(getWidth()/ 2,getHeight()/ 2)旋轉。 –

回答

1

你的代碼很混亂。這是我創建的GUI。

Animated Square

當創建一個Swing GUI,使用該模型/視圖/控制器模式。創建GUI模型和GUI視圖,以及一個或多個控制器來修改模型並重新繪製視圖。

以下是我對代碼所做的更改。

  1. 我創建了一個DrawingRectangle類來保存關於繪製矩形的信息。這個類是一個普通的舊Java對象,帶有getter和setter。這個類是GUI模型。

  2. 除了調用SwingUtilities invokeLater方法外,我將所有東西都移出了主方法。 invokeLater方法將創建和使用Swing組件的操作放在Event Dispatch thread上。 Oracle和我堅持所有的Swing應用程序都從Event Dispatch線程開始。

  3. 我在Q3_Circular類的構造函數中創建繪製矩形。通常,您將創建GUI模型,然後創建GUI視圖。

  4. 我重新安排了run方法中的JFrame代碼,使其處於正確的順序。我刪除了setSize方法並用pack方法替換它。我們不在乎JFrame有多大。我們關心繪圖板有多大。

  5. 我從JPanel創建了一個繪圖面板。在這裏,我們設置了繪圖面板的首選大小。我們擴展一個JPanel,所以我們可以覆蓋paintComponent方法。

  6. paintComponent方法除了繪製繪製矩形外什麼也不做。 paintComponent方法中沒有任何計算或繪畫。我添加了對super paintComponent方法的調用,以在繪製繪製矩形之前維護Swing繪畫鏈並清除繪圖面板。我使用x和y座標作爲矩形的中心而不是左上角繪製矩形。這是我在繪圖代碼中做的一個轉換。

  7. 我從Runnable創建了一個繪製動畫。如果你願意,你可以使用Swing Timer。我發現創建我自己的動畫代碼更容易。這是GUI控制器。這裏是我們進行計算的地方,更新模型並重繪繪圖面板。在重繪方法中,我使用SwingUtilities invokeLater方法在Event Dispatch線程上繪畫。我這樣做是因爲動畫線程是一個單獨的線程。

下面的代碼。我把所有的類放在一起,這樣我可以更容易地粘貼代碼。你應該將這些類分成不同的文件。

package com.ggl.testing; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.geom.Rectangle2D; 

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

public class Q3_Circular implements Runnable { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Q3_Circular()); 
    } 

    private static final int DRAWING_WIDTH = 300; 
    private static final int DRAWING_HEIGHT = DRAWING_WIDTH; 

    private DrawingRectangle drawingRectangle; 

    public Q3_Circular() { 
     int center = DRAWING_WIDTH/2; 
     Rectangle2D rectangle = new Rectangle2D.Double(center, center, 32D, 32D); 
     drawingRectangle = new DrawingRectangle(Color.RED, rectangle); 
    } 

    @Override 
    public void run() { 
     JFrame frame = new JFrame("Animated Square"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     DrawingPanel drawingPanel = new DrawingPanel(DRAWING_WIDTH, 
       DRAWING_HEIGHT, drawingRectangle); 
     frame.add(drawingPanel); 

     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 

     new Thread(new DrawingAnimation(drawingPanel, drawingRectangle)) 
       .start(); 
    } 

    public class DrawingPanel extends JPanel { 

     private static final long serialVersionUID = 8226587438110549806L; 

     private DrawingRectangle drawingRectangle; 

     public DrawingPanel(int width, int height, 
       DrawingRectangle drawingRectangle) { 
      this.setPreferredSize(new Dimension(width, height)); 
      this.drawingRectangle = drawingRectangle; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      g.setColor(drawingRectangle.getColor()); 

      Rectangle2D rectangle = drawingRectangle.getRectangle(); 
      int x = (int) Math.round(rectangle.getX()); 
      int y = (int) Math.round(rectangle.getY()); 
      int width = (int) Math.round(rectangle.getWidth()); 
      int height = (int) Math.round(rectangle.getHeight()); 
      g.fillRect(x - width/2, y - height/2, width, height); 
     } 

    } 

    public class DrawingAnimation implements Runnable { 

     private DrawingPanel drawingPanel; 

     private DrawingRectangle drawingRectangle; 

     public DrawingAnimation(DrawingPanel drawingPanel, 
       DrawingRectangle drawingRectangle) { 
      this.drawingPanel = drawingPanel; 
      this.drawingRectangle = drawingRectangle; 
     } 

     @Override 
     public void run() { 
      int xCenter = drawingPanel.getWidth()/2; 
      int yCenter = drawingPanel.getHeight()/2; 
      double radius = drawingPanel.getWidth()/3; 

      for (int degree = 0; degree < 360; degree++) { 
       double radians = Math.toRadians((double) degree); 
       double x = radius * Math.cos(radians) + xCenter; 
       double y = radius * Math.sin(radians) + yCenter; 
       drawingRectangle.setRectangleOrigin(x, y); 
       repaint(); 
       sleep(100L); 
      } 
     } 

     private void sleep(long interval) { 
      try { 
       Thread.sleep(interval); 
      } catch (InterruptedException e) { 

      } 
     } 

     private void repaint() { 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        drawingPanel.repaint(); 
       } 
      }); 
     } 
    } 

    public class DrawingRectangle { 

     private final Color color; 

     private Rectangle2D rectangle; 

     public DrawingRectangle(Color color, Rectangle2D rectangle) { 
      this.color = color; 
      this.rectangle = rectangle; 
     } 

     public void setRectangleOrigin(double x, double y) { 
      rectangle 
        .setRect(x, y, rectangle.getWidth(), rectangle.getHeight()); 
     } 

     public Color getColor() { 
      return color; 
     } 

     public Rectangle2D getRectangle() { 
      return rectangle; 
     } 

    } 

}