2013-11-28 6 views
2

У меня есть fairly simple JavaFX GUI application, у которого есть метка, показывающая, сколько времени осталось до запуска определенного действия. Для достижения этой цели я создал DownloadTimer класса, как показано ниже:TimerTask не может обновить текст метки JavaFX

public class DownloadTimer(){ 
    private int minutes;   
    private int seconds; 
    private Timer innerTimer = new Timer(); 
    private TimerTask innerTask; 
    private boolean isActive; 

    public DownloadTimer(int minutes, int seconds) { 
     if (seconds > 60) { 
      int minToAdd = seconds/60; 
      this.minutes = minutes; 
      this.minutes += minToAdd; 
      this.seconds = seconds % 60; 
     } else { 
      this.minutes = minutes; 
      this.seconds = seconds; 
     } 
    } 

    public void start() { 
     innerTask = new TimerTask() { 
      @Override 
      public void run() { 
       isActive = true; 
       System.out.println(getTime()); 
       if (seconds == 0 && minutes > 0){ 
        minutes -= 1; 
        seconds = 59; 
       } else if (seconds == 0 && minutes == 0){ 
        isActive = false; 
        innerTimer.cancel(); 
        innerTimer.purge(); 
        System.out.println("DownloadTimer DONE"); 
       } else { 
        seconds -= 1; 
       }  
      } 
     }; 
     innerTimer.scheduleAtFixedRate(innerTask, 0, 1000); 
    } 
} 

И потом, я создаю объект DownloadTimer и начинаю отсчет от моего главного (JavaFX) класса:

/* 
    code omitted for better readability 
*/ 

downloadTimer = new DownloadTimer(0, 5); 

// label gets the .getTime() value, which returns a formatted String like "00:05", "00:04", etc. 
lblTimer.setText(downloadTimer.getTime()); 

// start the countdown 
downloadTimer.start(); 

// create a new timer which checks if the downloadTimer is still counting 
final Timer timer = new Timer(); 
TimerTask timerTask = new TimerTask(){ 
    @Override 
    public void run(){ 
     if (downloadTimer.getIsActive() == false){ 
      timer.cancel(); 
      timer.purge(); 
      System.out.println("GUI timer DONE"); 
     } else { 
      // if it's still running, then continuously update the label's text 
      lblTimer.setText(downloadTimer.getTime()); 
      // this is where I get the error described below 
     } 
    } 
}; 
// repeat after 1000ms 
timer.scheduleAtFixedRate(timerTask, 0, 1000); 

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу установить текст метки lblTimer.setText(downloadTimer.getTime()); из основного класса, а ошибка, которую я получаю, - TimerThread.run() line: not available [local variables unavailable] как seen here.

Я читал около ScheduledThreadPoolExecutor и Java Timer vs ExecutorService, но мне любопытно, можно ли это сделать с помощью двух отдельных таймеров и таймерных задач. Любая помощь и/или советы будут очень признательны.

ответ

6

Я удивлен, что вы не видите исключения. Чтобы обновить ярлык из отдельного потока, необходимо запланировать обновление, которое должно выполняться в потоке FX:

Platform.runLater(new Runnable() { 
    public void run() { 
     lblTimer.setText(downloadTimer.getTime()); 
    } 
}); 
+0

Это работало безупречно! До сих пор я пытался понять это. Благодаря! –

+0

@ E.Normous Добро пожаловать! Моя максимальная маржа для hairpulling составляет 2 часа - после этого я начинаю искать совет ... :-) –

Смежные вопросы