2012-10-22 37 views
2

在這個簡單的代碼示例反彈球的動畫:Java代碼簡單的動畫只能運行在Windows

import javax.swing.JApplet; 
import javax.swing.JFrame; 
import java.awt.*; 

public class GraphicsMovement extends JApplet 
{ 
public static void pause() 
{ 
    try { 
     Thread.sleep(10); 
     } catch(InterruptedException e) { 
      } 
} 

public static void main(String args[]) 
{ 
    JApplet example = new GraphicsMovement(); 
    JFrame frame = new JFrame("Movement"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.add(example); 
    frame.setSize(new Dimension(500,300));  //Sets the dimensions of panel to appear when run 
    frame.setVisible(true); 
} 

    public void paint (Graphics page) 
    { 
int width = getWidth(); // width = the width of the panel which appears when run 
int height = getHeight(); // height = the height of the panel which appears when run. 

//Changes background color to a blueish color 
page.setColor(new Color (140,214,225)); 
page.fillRect(0,0,width,height); 
for(int i = 0; i <= 5; i++) 
{ 
    for (int j = 0; j <= 100; j++) 
    { 
     page.setColor(Color.YELLOW); 
     page.fillOval(100,55 + j,100,100); //draws a yellow oval 
     pause(); 
     page.setColor(new Color (140,214,225)); 
     page.fillOval(100,55 + j,100,100); //draws a blueish oval over the yellow oval 
    } 
    for (int k = 100; k >= 0; k--) 
    { 
     page.setColor(Color.YELLOW); 
     page.fillOval(100,55 + k,100,100); //draws a yellow oval 
     pause(); 
     if (k != 0) 
     { 
      page.setColor(new Color (140,214,225)); //draws a blueish oval over the yellow oval 
      page.fillOval(100,55 + k,100,100); 
     } 
    } 
} 
} 
} 

動畫繪製精美,運行(使用JCreator中)在Windows機器上,但會不能在用IntelliJ或Eclipse編譯的Mac OS X上運行。嘗試過兩種不同的OS X機器,並且都會繪製球和背景(經過漫長的等待),但不會繼續進行動畫。

在這裏,我缺少某種平臺特定的代碼嗎? 謝謝!

+2

在EDT _Don't_睡眠; _do_參見[* Swing *中的併發性](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/),特別是[*初始線程*](http://docs.oracle.com/ javase/tutorial/uiswing/concurrency/initial.html).. – trashgod

+0

對不起,我還是新來的java ......這是因爲慣例還是事實上,美國東部時間沉睡導致這些特殊問題?我閱讀了這些鏈接,但我不確定爲什麼線程在這個具體示例中很重要。 – kmypwn

+2

@kmypwn:您不需要'Thread.sleep()',而需要使用[javax.swing.Timer](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer。 HTML)。這是一個很棒的[示例](http://stackoverflow.com/a/9852739/1057230)。線程與您的具體示例無關,線程與整個Swing相關,這就是爲什麼@trashgod提到的那兩個鏈接。 –

回答

2

在任何會阻止或可能觸發重繪請求的paint方法中,都不會執行任何操作。

您應該始終致電super.paintXxx,這些方法在後臺做了很多工作,通常情況下可以更好。

您不需要(非常罕見的情況下)從頂級容器擴展,如JAppletJFrame。您最好創建一個自定義容器(如JPanel)並將其添加到其中(或執行自定義繪畫)。除了雙緩衝支持外,您還可以在部署選擇方面獲得靈活性。

不要欺騙你自己,你不控制油漆過程,這取決於重繪經理做出這些決定,但你可以「鼓勵」它來更新。當人們開始玩動畫時,這會造成最大的痛苦。

您應該在事件調度線程(EDT)影響之外修改動畫的「狀態」,或者在您的情況下,在paint上下文的外側修改動畫的「狀態」。

你的問題很簡單,一個簡單的javax.swing.Timer就可以解決它。更復雜的動畫可能需要一個「動畫」線程。

public class GraphicsMovement extends JApplet { 

    @Override 
    public void init() { 
     setLayout(new BorderLayout()); 
     add(new AnimatedPane()); 
    } 

    @Override 
    public void start() { 
    } 

    public class AnimatedPane extends JPanel { 

     private Timer timer; 
     private boolean colorSwitch = false; 

     private int yOffset = 0; 
     private int direction = 1; 

     public AnimatedPane() { 
      timer = new Timer(10, new ActionListener() { 
       public void actionPerformed(ActionEvent e) { 
//     colorSwitch = !colorSwitch; 
        yOffset += direction; 
        if (yOffset > 100) { 
         direction = -1; 
         yOffset = 100; 
        } else if (yOffset < 0){ 
         direction = 1; 
         yOffset = 0; 
        } 
        repaint(); 
       } 
      }); 
      timer.setRepeats(true); 
      timer.setCoalesce(true); 
      timer.start(); 

      setBackground(new Color(140, 214, 225)); 
     } 

     @Override 
     protected void paintComponent(Graphics page) { 
      super.paintComponent(page); 
      int width = getWidth(); // width = the width of the panel which appears when run 
      int height = getHeight(); // height = the height of the panel which appears when run. 

      if (colorSwitch) { 
       page.setColor(new Color(140, 214, 225)); 
      } else { 
       page.setColor(Color.YELLOW); 
      } 
      page.fillOval(100, 55 + yOffset, 100, 100); //draws a yellow oval 
     } 
    } 
} 

我關心的10毫秒「延遲」,這足以要我去面對一個合適的:P

您可能會發現通過閱讀...

的一些興趣

+0

在你改進的例子中,你忘記了J和K for循環實際上是在做什麼動畫(在原始中,它首先繪製橢圓,然後睡覺,然後使用背景顏色擦除橢圓並繼續下一次迭代) 。 J循環用於「下」動畫,K循環用於「上」動畫。 –

+0

@kim公平的點,沒有很多時間在我的腰帶下,並試圖找出困難,找出所有的循環 – MadProgrammer

+1

@Kim更新了專注於顏色變化的運動... – MadProgrammer

3

paint()方法在UI線程中調用,它應該儘可能快地返回。

那麼你將動畫代碼放在哪裏呢?答案很簡單:你需要把代碼放到一個單獨的線程中。

對於Windows和OS X之間的區別,我只能說它應該與他們如何安排線程或類似的事情有關。

+0

不確定這種差異是否真的是關於線程調度,更多關於圖形上下文是如何工作的。在Windows中,似乎更新立即傳播圖形內存 - 我可以想象OS X隱式使用雙緩衝區,在這種情況下,整個動畫首先被繪製到緩衝區(延遲),並且只有最後一幀的動畫從緩衝區翻轉到視頻內存。 –

+0

這很有道理 - 謝謝!這可以解釋球在屏幕上的延遲,因爲一旦顯示視圖,動畫就已經「完成」了。我會修改代碼並讓它在每一幀重新繪製屏幕。 – kmypwn

+0

所以我嘗試添加驗證和重繪語句的許多不同組合,但動畫仍然不會自行運行(有時,我可以通過切換窗口來強制它,但它仍然會出現毛刺)。你知道我應該在哪裏添加這些陳述嗎? – kmypwn