2014-02-20 44 views
1

我用我的主要方法後這樣調用重繪叫在我的JPanel中。 但是,如果我稍後刪除調用,只是做新的遊戲,它工作正常嗎?的Java的paintComponent不會被在與invokeLater的

這是我要做的事:

private void gameLoop() { 
    while(this.game) { 
     this.update(); 
     this.render(); 
    } 
} 

private void update() { 
    // TODO UPDATRES 
} 

private void render() { 
    super.repaint(); 
} 

而且程序設置的GUI可見之前,我添加使用super.add(屏幕屏幕)的組件,然後設置可見,這是我的屏幕類:

@SuppressWarnings("serial") 
public class Screen extends JPanel { 

    private Game game; 

    public Screen(Game bird) { 
     this.game = bird; 
    } 

    public void paintComponent(Graphics g) { 
     System.out.println("hey"); 
    } 
} 

爲什麼在invokelater運行時不重繪調用paintComponent?

SRC:

Game.java:

public class Game extends Window { 

    private static final long serialVersionUID = 1L; 

    private Screen gameScreen; 
    private boolean game = false; 

    public Game() { 
     this.gameScreen = new Screen(this); 
    } 

    public void initialize() { 
     super.setGameScreen(this.gameScreen); 
     this.game = true; 
     this.gameLoop(); 
    } 

    private void gameLoop() { 
     while(this.game) { 
      this.update(); 
      this.render(); 
     } 
    } 

    private void update() { 
     // TODO UPDATRES 
    } 

    private void render() { 
     super.repaint(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       Game bird = new Game(); 
       bird.initialize(); 
      } 
     }); 
    } 

} 

Window.java:

public class Window extends JFrame { 

    protected Window() { 
     super.setTitle("test"); 
     super.setSize(this.getPerfectSize()); 
    } 

    protected void setGameScreen(JPanel screen) { 
     super.add(screen); 
     super.setVisible(true); 
     System.out.println("added"); 
    } 

    private Dimension getPerfectSize() { 
     return new Dimension(350, 500); 
    } 
} 

Screen.java:

@SuppressWarnings("serial") 
public class Screen extends JPanel { 

    private Game game; 

    public Screen(Game bird) { 
     this.game = bird; 
    } 

    public void paintComponent(Graphics g) { 
     System.out.println("hey"); 
    } 
} 
+0

您可以將它作爲單個[MCVE](http://stackoverflow.com/help/mcve)發佈,而不是斷開連接的代碼片段嗎? –

+0

@KevinWorkman當然,補充。 – Artemkller545

回答

1

這樣做的原因是因爲gameLoop()中的無限循環。

當您直接從main()方法執行Game構造函數和initialize()方法時,您位於主線程中。無限循環在主線程上執行。當您調用repaint()時,EDT可以自由調用paintComponent()方法。

當您從SwingUtilities.invokeLater()執行Game構造函數和initialize()方法時,您將該代碼放在EDT上。然後在EDT上執行無限循環。

由於您使用您的方法阻止了無限循環內的EDT,這意味着EDT不能自由調用paintComponent()方法。它陷入了無限循環。

解決方法是將您的gameLoop放在另一個線程上。例如:

public void initialize() { 
    super.setGameScreen(this.gameScreen); 
    this.game = true; 
    this.startGameLoop(); 
} 

private void startGameLoop() { 
    new Thread(){ 
     public void run(){ 
      while(game) { 
       update(); 
       render(); 
      } 
     } 
    }.start(); 
} 

只要確保您的gui的任何更改發生在EDT上。請參閱concurrencySwing concurrency教程以獲取更多詳細信息。

+0

不是使用Swing Timer,最重要的是使用swing.JWindow而不是awt.Window – mKorbel