2017-05-20 4 views
0

私はJavaクラスで最終プロジェクト用のブラックジャックプログラムを作成しています。ラウンドの最後に自分のカードを与えるディーラーをシミュレートしたいと思います。私はちょっと休憩を見せるために1秒間whileループの各繰り返しを眠りたい。以下は、私がスタックオーバーフローで読んだ異なるスレッドに基づいて取った2つの試みですが、どちらも動作しません。JavaFX新しいラベルを表示してループの各繰り返しをスリープします

Timeline timeline = new Timeline(
     new KeyFrame(Duration.millis(1000), event -> 
     { 
      if(dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21)) 
      { 
       newCard(dealer, mainDeck.deal(), false); 
       System.out.println("Running Here!"); 
       LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining"); 
      } 
     }) 
); 
timeline.setCycleCount(1); 
System.out.println("Starting loop!"); 

と、この1:

while (dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21)) 
{ 
    new Thread(() -> 
    { 
     try 
     { 
      Thread.sleep(1000); 
      newCard(dealer, mainDeck.deal(), false); 
      LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining"); 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
    }).run(); 
} 

私は私が前にタイムラインで働いたことがないので、最初の例と間違っているものをあまりにもわかりません。第2の方法としては、睡眠時間の合計を数え、その時間の間私のプログラムを凍結するように見える。 I.ループが3回行った場合、私のプログラムは3秒間スリープ状態になります。次に、すべてのラベルを一度に吐き出します。

+0

何度も言われていますが、私はもう一度言っています。 JavaFXアプリケーションで 'Thread.sleep'を使わないでください。それはUI全体を停止させ、私はかなり確信しています、それはあなたが望むものではありません。 –

+0

@ChandlerBingそれでは、代わりに何を使うべきですか?私はそれが起こっていることを理解していますが、別の解決策が必要なので投稿しています – Noah

+0

@ChandlerBing "JavaFXアプリケーションで' Thread.sleep'を使わないでください。 "というのは本当に正しいわけではありません:' Thread.sleep '(または他のブロッキング呼び出し)*をJavaFXアプリケーションスレッド*上に作成します。 OPがここで何をしようとしているのか(バックグラウンドで 'start()'の代わりに 'run()'を呼んでいる)バックグラウンドスレッドで行うのは良いことです。 –

答えて

1

タイムラインは、KeyFrameの1つのみで、サイクル数は1に設定されています(タイムライン全体が1回実行されるため)。

あなたはINDEFINITEにサイクル数を設定することもできます(それは永遠に繰り返される)と明示的に条件が満たされたときにタイムラインを停止します。

Timeline timeline = new Timeline(); 
KeyFrame keyFrame = new KeyFrame(Duration.millis(1000), event -> { 

    if(dealer.getScore() >= 17 && (dealer.getScore() >= player.getScore() || dealer.getScore() > 21)) { 
     timeline.stop(); 
    } else { 
     newCard(dealer, mainDeck.deal(), false); 
     System.out.println("Running Here!"); 
     LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining"); 
    } 
}); 

timeline.getKeyFrames().add(keyFrame); 
timeline.setCycleCount(Animation.INDEFINITE); 
timeline.play(); 

あなたのスレッドのソリューションは、問題のカップルを持っています。まず、スレッドの実行可能ファイルをバックグラウンドスレッドで実行していません。Thread.run()は、FXアプリケーションスレッドである現在のスレッドでrunnableを実行するだけです。したがって、あなたのThread.sleep()がFXアプリケーションスレッドをブロックし、UIがレンダリングされず、応答しなくなります。実際に新しいスレッドを開始するには、代わりにThread.start()に電話する必要があります。

2番目の問題は、あなたが呼び出したnewCard()setText()メソッドがUIを変更することです。これはバックグラウンドスレッドからは実行できません。 FXアプリケーションスレッドでこれらを実行する必要があります:Platform.runLater(...)にラップすることでこれを行うことができます。

最後に、対処するカードごとに新しいスレッドを作成していて、修正したらそのスレッドを起動します。したがって、各カードは本質的に同じスレッドで処理されます。これはあなたが望むものではありません。バックグラウンドスレッドが一度に1枚のカードを扱い、各カード間で一時停止したいとします。したがって、1つのバックグラウンドスレッドを作成し、ループ全体を実行してください:

new Thread(() -> { 
    while (dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21)) { 
     try { 
      Thread.sleep(1000); 
      newCard(dealer, mainDeck.deal(), false); 
      LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
}).start(); 
+0

私はあなたの提供された例を使ってタイムラインを動作させることができましたが、問題は残りのコードがアニメーションが終了するのを待つことではありません。アニメーションが終了するまで待つようにプログラムが必要です。どのようにこれを行うにはどのような考え? – Noah

関連する問題