Все операции пользовательского интерфейса должны выполняться в потоке приложений FX. Вы можете вызвать Platform.runLater(...)
из фонового потока и передать ему Runnable
, который будет выполняться в потоке приложения FX.
Нет необходимости прерывать существующий поток. Если вы переупорядочите код так, чтобы вы спали сначала, а затем проверьте, то поток все равно собирается завершиться:
public Thread getCounter() {
if(counter == null) {
counter = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 5; i >= 0; i--) {
try {
Thread.sleep(1000);
System.out.println(i);
if(i == 0) {
System.out.println("Time is up");
Platform.runLater(this::timeIsUp);
System.out.println("test");
break;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
});
counter.setDaemon(true);
}
return counter;
}
Теперь вы можете удалить вызов прерывания из метода timeIsUp()
.
public void timeIsUp() {
if (turn+1 < nbPlayers) {
turn++;
} else {
turn = 0;
}
getBtnDes().setDisable(false); // Disable a button
destroyCardPane(); // remove an AnchorPane from this.children()
}
Обратите внимание, что вы можете делать все это без потоков, используя Timeline
:
Timeline timeline = new Timeline();
for (int i = 5 ; i >= 0 ; i=--) {
final int count = i ;
KeyFrame frame = new KeyFrame(Duration.seconds(5-i), e -> System.out.println(count));
timeline.getKeyFrames().add(frame);
}
timeline.setOnFinished(e -> {
System.out.println("Time is up");
timeIsUp();
});
timeline.play();
Здесь нет блокировки (поэтому нет необходимости в потоках), а обработчик событий ключевого кадра и обработчик onFinished
выполняются в потоке приложений FX, поэтому безопасно обновлять там пользовательский интерфейс.