2016-04-01 3 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メソッドは、あなたが呼び出すことができないメソッドで、アプリケーションのエントリポイントとされています。あなたの主な方法で

、この操作を行います。このRunnableはイベントディスパッチスレッドで実行され、UIに関連するすべてのアクションの前にUIの準備ができようになります

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

を。

UIを準備したら、フレームを作成してゲームにリンクしたとします。次に、フレームとゲームのコントローラのような役割を果たすクラスを使用して、興味のあるイベントを聴いて、必要なときにUIを更新します。

イベントが発生するたびにこのゲームを実行するウィンドウを作成する必要がある場合は、このウィンドウをクラスとして定義する必要があります。このクラスのインスタンスを作成し、ウィンドウを可視にするだけです。または、ゲームを再起動するだけでよい場合は、アプリケーション全体でクラスのインスタンスを1つ使用し、その中でゲームを再起動します。コントローラークラスは、ゲームの再起動とUIの更新をゲームに通知するために常に便利です。

0

mainコードをコンストラクタに移動する必要があります。mainは、実行する第1クラスまたはメインクラスのみにする必要があります。

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); 
    } 
} 

次に、あなたのようにそれを呼び出す:、あなたが使用する必要がある他の回答で述べたように、あなたもConstructorsClasses and Objects

についての詳細を読んでください、Thread.sleep()アプリケーションがフリーズする原因となります

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); 
    } 

} 

Swing Timerを別のスレッドで処理する代わりに、アプリケーションがフリーズすることはありません。

Thread.sleep()を使用すると、アプリケーションは内部で時間を待ってから再描画します。

1

これは、2番目のケースでは、ActionListenerからmainメソッドを呼び出すため、UIスレッドでmainメソッドを実行しているためです。また、このコードでアクティブな待機ブロックがあるため、UIは決して何も描画できません。あなたはのjavax.swing.Timerをチェックアウトし、Timer

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

私はTimerを使用しようとしましたが、実装方法は実際には分かりません。 – Antoshjke

+1

Web上にはSwingのチュートリアルがたくさんあり、その使い方を示すことができます – ControlAltDel

0

を使用して実装して、私は下にコピーされてきたループを交換する必要がありAsothersは、あなたが)(自分をメイン呼び出してはならない、と述べています。つまり、ループ内にThread.sleep()を置くことはできません。スレッドをブロックするEventDispatchThreadで実行され、再描画されることはありません。ループを実行するには、SwingWorkerを使用する必要があります。