2017-04-21 109 views
0

我正在嘗試爲學習目的製作自己的Snake版本。一切似乎工作正常,但如果我想要我的框架重新粉刷,我必須手動調整我的窗口。這裏是我的代碼:只有在調整窗口大小後才能更新JFrame

package snake; 

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

public class PlayGame extends JPanel implements Runnable{ 

    public boolean animate = false;   
    public final int FRAME_DELAY = 750; 

    PickupBall b = new PickupBall(); 
    Snake bob = new Snake(); 


    public synchronized void start() { 
     animate = true; 
    } 

    public synchronized void stop() { 
     animate = false; 
    } 
    private synchronized boolean animationEnabled() { 
     return animate; 
    } 

    @Override 
    public void run(){    
     while(true){  
      if (animationEnabled()){      
       repaint();      
      } 
      try { 
       Thread.sleep(FRAME_DELAY); 
      } 
      catch (InterruptedException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    }   

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

     b.draw(g); 
     bob.draw(g);    
    }   

    public static void main(String[] args) {  
     JFrame jfr = new JFrame("Snake"); 
     jfr.setSize(640,640); 
     jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
     jfr.setResizable(true); 

     PlayGame p = new PlayGame(); 

     jfr.setContentPane(p); 

     p.setBackground(Color.WHITE);    

     p.start();    

     new Thread(p).start();    
     jfr.setVisible(true);  

    } 


} 

爲什麼不重繪()觸發沒有改變幀的大小?我得到了相關性,但是它對於爲什麼當它處於while(true)循環時需要這樣的觸發器是沒有意義的。

我在這裏錯過了什麼?

編輯1: 刪除線程對象 替換t.start()與p.start()

編輯2: 新增new Thread(p).start();和現在的作品!謝謝。

編輯3: 刪除revalidate();

+0

PlayGame p = new PlayGame(); 線程t =新線程(p); t.start(); –

+1

't.start()',但從來沒有'p.start()',所以'animate'總是'false'。 – kiheru

+0

好吧,這是否意味着線程對象是毫無意義的? –

回答

0

新增new Thread(p).start();

仍然不知道如何或爲何這是不同的,以 Thread t = new Thread(p); t.start();

但它的工作。

+0

它們沒有區別,問題不在那裏。問題是你從'Thread'類中調用'start',而不是'PlayGame'類中的'start'。他們都是完全不同的方法,你需要調用兩者。 「Playgame」中的「開始」可以具有任何你想要的名稱,誤導它與「線程」中的方法具有相同的名稱。 – Berger

0

您在工作線程執行repaint(),而不是在事件分派胎面(EDT)這實際上是繪製到屏幕上的唯一的一個。

您必須使用SwingUtilities靜態方法invokeLater()invokeAndWait()在EDT中將呼叫排隊到repaint()

+0

您能告訴我嗎?我不知道在哪裏放,谷歌沒有幫助。 –

+0

'repaint'是線程安全的,因爲它將實際的繪畫事件發佈到要處理的EDT上 – MadProgrammer