我有一个主窗口,当我按一个按钮时,将打开另一个窗口。
一定时间后,该窗口应关闭。因为它扩展了stage
,所以我使用super.close
,但是它不起作用。我能做什么?是因为我在服务任务中关闭了它?
public Game(int width, int height, int time) {
this.width = width - 15;
this.height = height - 15;
this.time = time;
this.layout = generateLayout();
this.scene = new Scene(this.layout, this.width, this.height);
super.initModality(Modality.APPLICATION_MODAL);
super.setScene(scene);
super.setResizable(false);
super.setTitle(TITLE);
this.cicle.reset();
this.cicle.start();
super.showAndWait();
}
在cicle
内,我称close()
有点困惑,但这是cicle
服务任务:
Service<Void> cicle = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
volatile boolean waiting = false;
@Override
protected Void call() throws Exception {
Timer.start();
while (Timer.update() / 1000 < time) {
System.out.println(Timer.update())
}
close();
return null;
}
};
}
};
答案 0 :(得分:1)
问题是您正试图从JavaFX Application Thread以外的其他线程 关闭Stage
。查看Stage
的文档,您将看到:
必须在JavaFX上构造和修改阶段对象 应用程序线程。
JavaFX应用程序线程是在启动过程中创建的 JavaFX运行时进程。请参阅Application类和 Platform.startup(Runnable)方法以获取更多信息。
然而Service
在启动时将在 background 线程上执行其Task
。具体地,call()
的{{1}}方法在所述后台线程上执行。我刚刚测试过尝试在后台线程上关闭Task
来查看发生了什么(是否会引发异常)。结果是Stage
。
您没有看到它的原因是您没有观察到java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
的失败。您可以查看the answer to this question来查看监视失败的方法。答案专门针对Service
,但Task
中也存在相同的行为。
要使代码正常工作,需要做的是确保在JavaFX Application Thread上调用Service
。最简单的方法是将close()
封装在Platform.runLater(Runnable)
调用中。
close()
您还可以覆盖Service.succeeded()
,它将始终在JavaFX Application Thread上调用(但仅在Service<Void> cicle = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
volatile boolean waiting = false;
@Override
protected Void call() throws Exception {
Timer.start();
while (Timer.update() / 1000 < time) {
System.out.println(Timer.update())
}
Platform.runLater(() -> close()); // wrapped in Platform#runLater
return null;
}
};
}
};
成功的情况下)。在这种情况下,您将从Service
方法中删除对close()
的调用。
call()
还有其他方法:收听Service<Void> cicle = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
volatile boolean waiting = false;
@Override
protected Void call() throws Exception {
Timer.start();
while (Timer.update() / 1000 < time) {
System.out.println(Timer.update())
}
return null;
}
};
}
@Override
protected void succeeded() {
close();
}
};
属性,使用state
等...