2016-07-30 17 views
-1

javafxを使用して複数のカウントダウンタイマーを同時に実行しようとしています。現在使用されているマルチスレッドです。今私は、私はそれを印刷するためにコントローラのクラスにアクセスできないので、そうすることができませんが、画面上に表示するようにラベルでタイマーを印刷しようとしています。私はどのように私のスレッドクラスを使用してラベルにタイマー値を印刷することを達成するのですか?私のタイマーの値は、グリッドペインのラベルに印刷する必要がありますので、私はコントローラクラスから制約を取得し、それに応じて印刷します。JavaFXマルチスレッドおよびコントローラクラス

package tabapplication; 
import java.util.Timer; 
import java.util.TimerTask; 
import tabapplication.TabApplication; 
import tabapplication.FXMLDocumentController; 
class Rdt implements Runnable { 
    private Thread t; 
    private String threadName; 

    Rdt(String name){ 
     threadName = name; 
     System.out.println("Creating " + threadName); 
    } 
    public void run() { 
     System.out.println("Running " + threadName); 
     try { 
      final Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask() { 
      int s = 60; 
      int m=30; 
      public void run() { 
       s--; 
       if(s<0 && m>0) 
       {m--; 
       s=59; 
       } 
       if(s<10) 
       { System.out.println(Integer.toString(m)+":"+0+Integer.toString(s)); } 
       else 
       {System.out.println(Integer.toString(m)+":"+Integer.toString(s));} 


       if(m==0 && s==0) 
        timer.cancel(); 
      } 
     }, 0, 10); 
      Thread.sleep(50); 
    } catch (InterruptedException e) { 
     System.out.println("Thread " + threadName + " interrupted."); 
    } 
    System.out.println("Thread " + threadName + " exiting."); 
    } 

    public void start() 
    { 
     System.out.println("Starting " + threadName); 
     if (t == null) 
     { 
     t = new Thread (this, threadName); 
     t.start(); 
     } 
    } 
    public static void main(String args[]) { 

     Rdt R1 = new Rdt("Thread-1"); 
     Thread obj1=new Thread(R1); 
     obj1.start(); 

     Rdt R2 = new Rdt("Thread-2"); 
    Thread obj2=new Thread(R2); 
    obj2.start(); 
    } 
} 
+0

「私はコントローラクラスにアクセスすることはできません... "。何故なの?おそらく、あなたのJavaFXアプリケーションでは、コントローラからこれらのタイマーを実際にインスタンス化するでしょう(例えば、ユーザーアクションへの応答として)。 –

+0

タイマーを独立して同時に実行したいのですが、私の場合は1回だけ実行され、他の停止が実行されます。そのため、私は異なるタイマーのスレッドを使用しています。 fxmlのコントローラから私は上記のJavaコードを呼び出しています。私はグリッドの特定の位置に各タイマーを配置する必要があります。それを達成することはできません。 –

答えて

1

あなたRdtクラスの時間は、それが変化を表したときに実行するコールバックを与えます。これは、例えば、Consumer<String>の形態であることができます。

public class Controller { 

    @FXML 
    private Label timerLabel ; 

    @FXML 
    private void startTimer() { 
     Rdt timer = new Rdt("Timer-1", timerLabel::setText); 
     timer.run(); 
    } 
} 

asidesのカップル:

class Rdt implements Runnable { 
    private Thread t; 
    private String threadName; 

    private Consumer<String> callback ; 

    Rdt(String name, Consumer<String> callback){ 
     threadName = name; 
     System.out.println("Creating " + threadName); 
     this.callback = callback ; 
    } 
    public void run() { 
     System.out.println("Running " + threadName); 
     try { 
      final Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask() { 
      int s = 60; 
      int m=30; 
      public void run() { 
       s--; 
       if(s<0 && m>0) 
       {m--; 
       s=59; 
       } 
       if(s<10) 
       { callback.accept(Integer.toString(m)+":"+0+Integer.toString(s)); } 
       else 
       {callback.accept(Integer.toString(m)+":"+Integer.toString(s));} 


       if(m==0 && s==0) 
        timer.cancel(); 
      } 
     }, 0, 10); 
      Thread.sleep(50); 
    } catch (InterruptedException e) { 
     System.out.println("Thread " + threadName + " interrupted."); 
    } 
    System.out.println("Thread " + threadName + " exiting."); 
    } 

    // ... 
} 

今すぐあなたのコントローラクラスからあなただけでタイマーを開始することができます

  1. ここにスレッドを作成する必要はありません。 Timerクラスはすでにです。これはバックグラウンドスレッドを作成するため、明示的に作成することなくバックグラウンドスレッドで実行されます。
  2. あなたは実際に多くの場所でホイールを再発明しています。標準ライブラリにはすでに、例えば、Duration classがあり、分と秒を表すために使用でき、すでにすべての算術演算を実装しています。考えてみましょう:

    public class Rdt { 
    
        private String name ; 
    
        private Consumer<Duration> callback ; 
    
        private Duration time ; 
    
        public Rdt(String name, Consumer<Duration> callback) { 
         this.name = name ; 
         this.callback = callback ; 
        } 
    
        public void startTimer() { 
         Timer timer = new Timer(); 
         time = Duration.ofMinutes(30); 
         timer.scheduleAtFixedRate(new TimerTask() { 
          @Override 
          public void run() { 
           time = time.minusSeconds(1); 
           callback.accept(time); 
           if (time.isZero()) { 
            timer.cancel(); 
           } 
          } 
         }, 0, 10); 
        } 
    } 
    

と同様に、DateTimeFormatterクラスを使用すると、どうなるのコントローラからなる、文字列としてうまくフォーマット倍にする方法を知っている:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("mm:ss"); 
Rdt timer = new Rdt("Timer-1", time -> timerLabel.setText(formatter.format(time))); 
timer.start(); 
+0

時間を印刷したいラベルがグリッドペインの内側にある場合、そこに印刷するにはどうしたらいいですか?現在、グリッドペインはシーンビルダを使用して作成されたので、fxmlファイルに存在します。私はコントローラクラスを通して時間を印刷していました。アプローチは、タイマーの異なるインスタンスのRdtクラスを呼び出すと、コントローラクラスに私は達成することはできませんラベルに印刷する値を返します。同じことを行うための編集や代替手段を提案することはできますか? @James_D –

+0

プライベートコンシューマコールバック; generationgエラーは、クラスRdtのクラスのシンボルを見つけることができません –

+0

Fr.最初のコメント、答えは明示的にそれを行う方法を示しています。あなたが何が欠けているか分からない。第二に、あなたは輸入品を入れましたか?インポート後のパッケージ –

関連する問題