TimerTask не может обновить текст метки JavaFX

У меня есть достаточно простое приложение с графическим интерфейсом JavaFX с меткой который показывает, сколько времени осталось до начала определенного действия. Для этого я создал класс DownloadTimer, как показано ниже:

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 и запускаю обратный отсчет из класса Main (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] как здесь.

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


person E. Normous    schedule 28.11.2013    source источник


Ответы (1)


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

Platform.runLater(new Runnable() {
    public void run() {
        lblTimer.setText(downloadTimer.getTime());
    }
});
person Andrey Chaschev    schedule 28.11.2013
comment
Это сработало безупречно! Я пытаюсь понять это уже три дня. Спасибо! - person E. Normous; 28.11.2013
comment
@E.Normous Добро пожаловать! Мой максимальный запас на выдергивание волос составляет 2 часа - после этого я начинаю искать совет... :-) - person Andrey Chaschev; 29.11.2013