我有一个带有网格(GridPane)的简单应用程序和一个带有开始/停止按钮的简单工具栏。我的按钮动作看起来是这样的:
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
grid.change();
}
});当我点击它的时候,网格的变化就像它应该做的那样。由于场景图不是线程安全的,而且只由FX应用程序线程提供,所以我已经放置了一个服务,应该更新我的网格:
private Service task = new Service(){
@Override
protected Task createTask() {
System.out.println("Task created");
return new Task<Void>() {
@Override
protected Void call() throws Exception {
for (int i = 0; i < 3; i++) {
System.out.println("calling");
Platform.runLater(new Runnable(){
@Override
public void run() {
System.out.println("running");
grid.changeGeneration();
try {
Thread.sleep(1500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
return null;
}
};
}
};当我运行我的应用程序时,按下按钮后,它会给我这个
创建的调用运行运行的任务
它重新计算网格模型,但它不想呈现视图,实际上,在完成所有Platform.runLater之后,FX呈现网格,而不是在每个running之后。我的错误在哪里?如何使FX在每个running之后呈现网格
更新:获得了解决方案这里,但仍然不能完全理解为什么它拒绝工作。
发布于 2012-12-11 18:27:20
这里的原因可能是您快速地连续发布了三个Runnables,而FX队列没有机会在中间重新绘制代码。由于缺少更好的名称,重绘不会立即执行,而是添加到事件队列的末尾。因此,基本上,外部循环触发三个Runnables,事件队列最后看起来如下所示:Runnables
此外,睡眠实际上阻塞了事件队列--您永远不应该在Platform#runLater(...)中调用Platform#runLater(...)。实际上,您正在阻止3x1500 millis的所有事件处理,包括重绘和用户输入。
将Thread.sleep()从Runnable中移出,您将解决这两个问题。事件队列将接收GridChange,有1.5秒的时间更新UI,接收下一个GridChange等等……
https://stackoverflow.com/questions/13820734
复制相似问题