2016-07-30 48 views
-1

我想用javafx同時執行多個倒計時定時器。目前使用多線程。現在我正試圖在標籤上打印定時器,以便在屏幕上顯示,但無法這樣做,因爲我無法訪問控制器類來打印它。我如何實現使用我的線程類打印標籤上的計時器值。我的計時器值應該打印在gridpane中的標籤中,所以我從控制器類中獲取約束,然後相應地打印。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

我希望計時器能夠獨立同時運行,但在我的情況下,只有一次運行和其他停止。這就是爲什麼我爲不同的定時器使用線程。我從上面提到的Java代碼調用fxml控制器。但我必須將每個計時器放在網格中的特定位置。無法實現這一點。 –

回答

1

給你Rdt類回調到時候它代表的變化來執行。這可能是一個Consumer<String>的形式,例如:

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

    // ... 
} 
從你的控制器類

現在你可以開始與定時器:

public class Controller { 

    @FXML 
    private Label timerLabel ; 

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

一對夫婦旁白的:

  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

如果我想要打印時間的標籤位於網格窗格內,我該如何打印它。目前,gridpane是使用場景構建器製作的,因此它存在於fxml文件中。我通過我的控制器課打印時間。方法是調用Rdt類來獲取計時器的不同實例,並將值返回給控制器類,以便將其打印在標籤中,這是我無法實現的。你能建議編輯或替代措施來執行相同的操作嗎? @James_D –

+0

私人消費者回調;代碼錯誤無法在類Rdt –

+0

Fr.中找到符號。第一條評論,答案顯示瞭如何做到這一點。不知道你錯過了什麼。第二,你是否包括進口? –