2016-04-01 37 views
2

基本上我有一個主類的遊戲。從其他職業打電話時JFrame不加載

public static void main(String[] args) throws InterruptedException { 
    JFrame frame = new JFrame("Mini Tennis"); 
    Game game = new Game(); 
    frame.add(game); 
    frame.setSize(300, 400); 
    frame.setResizable(false); 
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    while (true) { 
     game.move(); 
     game.repaint(); 
     Thread.sleep(10); 
    } 
} 

當我直接加載類它工作正常。

enter image description here

但是,當我從另一個類調用它,它不會畫什麼。

private void btnGameActionPerformed(java.awt.event.ActionEvent evt) {           
    try { 
     String[] args = null; 
     Game.main(args); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(DrawerMain.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

enter image description here

,幾秒鐘後,它描繪的是我失去了比賽。所以基本上游戲正在運行,但我什麼也做不了,我什麼都看不到。

enter image description here

回答

0

首先,你不應該運行一切從你的主線程。並且main方法不適合您調用,它應該是您的應用程序的入口點。

在main方法,這樣做:

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     createAndShowGUI(); // in this method, you create your frame and other UI components and show them 
    } 
}); 

Runnable將在事件調度線程運行,將使得UI相關的UI任何操作之前準備就緒。

一旦你準備好你的用戶界面,就說你創建了框架並將其鏈接到遊戲。然後使用一個類似框架和遊戲控制器的類來監聽感興趣的事件,並在需要時更新UI。

如果你需要創建一個運行這個遊戲的窗口,每次發生一些事件時,你應該把這個窗口定義爲一個類。你只需要創建這個類的一個實例並使窗口可見。或者,如果您只需要重新啓動遊戲,則可以在整個應用程序中使用該類的單個實例,並僅在其中重新啓動遊戲。控制器類對於通知遊戲重啓以及更新UI總是有用的。

0

您需要將main代碼移動到構造函數中,main應該只在第一個類或您要運行的「主」類上。

main method是您的應用程序運行的入口點,您不應該像調用其他方法那樣調用它。

public Game() { 
    JFrame frame = new JFrame("Mini Tennis"); 
    Game game = new Game(); 
    frame.add(game); 
    frame.setSize(300, 400); 
    frame.setResizable(false); 
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    while (true) { 
     game.move(); 
     game.repaint(); 
     Thread.sleep(10); 
    } 
} 

然後你怎麼稱呼它爲:

private void btnGameActionPerformed(java.awt.event.ActionEvent evt) {           
    try { 
     String[] args = null; 
     Game game = new Game(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(DrawerMain.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

在其他的答案中提到你應該閱讀更多關於ConstructorsClasses and Objects

此外,Thread.sleep()會導致應用程序凍結,你應該使用一個Swing Timer而不是在另一個線程中處理它,所以你的應用程序不會凍結。

隨着Thread.sleep()您的應用程序將重新繪製它之前等待它裏面的時間。

1

原因是在第二種情況下,您從ActionListener調用主方法時,您正在UI線程上運行主方法。而且,由於您在此代碼中擁有主動等待區塊,因此UI永遠無法繪製任何內容。你應該看看javax.swing.Timer中,並與使用Timer

while (true) { 
     game.move(); 
     game.repaint(); 
     Thread.sleep(10); 
    } 
+0

我試過使用Timer,但並沒有真正知道如何實現它。 – Antoshjke

+1

網上有很多Swing教程,可以告訴你如何使用它 – ControlAltDel

0

Asothers說的實現來替代我下面複製循環,你不應該調用的main()自己。也就是說,你的循環中不能有Thread.sleep() - 如果它在EventDispatchThread上運行(它必須是這樣),這將阻塞該線程,並且你永遠不會得到重繪。您需要使用SwingWorker來完成循環。