2016-12-03 68 views
1

我一直在嘗試使用場景生成器使用JavaFX創建一個計時器,但是我一直在創建線程時遇到了一些問題。每當我點擊開始按鈕,應用程序就會落後,永遠不會真正更新文本。我一直在嘗試使用Platform.runLater(),但正如前面提到的,一切都落後了,因此。JavaFX計時器線程問題

這裏是控制定時器,鏈接到特定的按鈕上FXML文件的方法:

@FXML 
private void startTimer(){ 
    System.out.println("started"); 
    stopWatch.startTimer(); 

} 

@FXML 
private void pauseTimer(){ 
    stopWatch.pauseTimer(); 
} 

@FXML 
private void stopTimer(){ 
    System.out.println("stopped"); 
    stopWatch.stopTimer(); 
} 

@FXML 
public void updateTimer(long dT){ 

    //System.out.println(((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000)); 
    Platform.runLater(() ->{ 
     timer.setText(String.valueOf(dT/1000)); 
    }); 
} 

這裏是StopWatch.java類:

package sled.timer.address.model; 

import sled.timer.address.view.PersonOverviewController; 

public class StopWatch implements Runnable{ 

private Thread runThread; 
public boolean running = false; 
public boolean paused = false; 


private long summedTime = 0; 

PersonOverviewController personOverviewController; 

String time = ""; 

public void count(){ 

} 
public StopWatch(PersonOverviewController personOverviewController){ 
    this.personOverviewController = personOverviewController; 

} 
public void startTimer(){ 
    running = true; 
    paused = false; 

    runThread = new Thread(this); 
    runThread.start(); 
} 

public void pauseTimer(){ 
    paused = true; 
} 

public void stopTimer(){ 
    running = false; 
    paused = false; 
} 
@Override 
public void run() { 
    // TODO Auto-generated method stub 
    long startTime = System.currentTimeMillis(); 
    while(running && !paused){ 
     personOverviewController.updateTimer(summedTime + (System.currentTimeMillis() - startTime)); 
    } 
    if(paused) 
     summedTime += System.currentTimeMillis() - startTime; 

    else 
     summedTime = 0; 

} 

public long getSummedTime(){ 
    return summedTime; 
} 

任何幫助表示讚賞。

回答

0

您不限制線程的更新頻率。通過這種方式,您可以發佈很多Runable以便執行應用程序線程,因此幾乎沒有時間執行事件處理和佈局,從而使您的應用程序以這種方式運行。

此外,您不會同步對布爾標誌的訪問,也不會使它們成爲volatile,這意味着值更改不一定對其他線程可見。

相反,你應該確保沒有更多的更新張貼直到最後Runnable已經啓動:

private final Object updaterLock = new Object(); 
private final boolean updating = false; 
private final long value; 

public void updateTimer(long dT) { 
    synchronized (updaterLock) { 
     value = dT; 
     if (!updating) { 
      updating = true; 
      Platform.runLater(() -> { 
       synchronized (updaterLock) { 
        updating = false; 
        timer.setText(Long.toString(value/1000)); 
       } 
      }); 
     } 
    } 
} 
public class StopWatch implements Runnable{ 

    ... 

    public volatile boolean running = false; 
    public volatile boolean paused = false; 

但是考慮使用the AnimationTimer class做更新。此課程的更新頻率有限。