java - 在 JavaFx 应用程序中使用 Thread.sleep()
问题描述
我尝试制作一个显示按钮的应用程序。当我单击按钮时,场景应该显示一些文本(添加标签)几秒钟,然后文本应该消失(从场景中删除标签)。但事实上,当我点击按钮时,什么也没有发生。
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
StackPane pane = new StackPane();
Button btn = new Button();
Label lb = new Label("Start");
pane.getChildren().addAll(btn);
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(pane, 300, 275));
primaryStage.show();
btn.setOnAction(e->{
pane.getChildren().addAll(lb);
try {
Thread.sleep(300);
} catch (Exception ex) {
ex.printStackTrace();
}
pane.getChildren().removeAll(lb);
});
}
public static void main(String[] args) {
launch(args);
}
}
解决方案
btn.setOnAction(e->{
pane.getChildren().addAll(lb);
PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
pause.setOnFinished(e -> pane.getChildren().removeAll(lb));
pause.play();
});
您的方法不起作用的原因是 JavaFX 有效地使用单个线程来呈现和处理用户事件。它将以固定的时间间隔更新屏幕(在当前实现中每秒 60 次),但出于同步原因,必须等待当前正在处理的任何未决事件首先完成。因此,您的原始代码添加标签,暂停 0.3 秒,然后删除标签。FX 应用程序线程被整个过程占用,因此 FX 框架永远没有机会在场景发生时重绘场景。
这里的底线是,您永远不应该通过调用sleep()
或执行长时间运行的操作来阻塞 FX 应用程序线程。
更新以回应评论中的其他问题:
要禁用所有事件处理,您可以调用setDisable(true)
场景的根节点。因此,为了防止在显示标签时进行事件处理:
btn.setOnAction(e->{
pane.getChildren().addAll(lb);
pane.setDisable(true);
PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
pause.setOnFinished(e -> {
pane.getChildren().removeAll(lb));
pane.setDisable(false);
});
pause.play();
});
推荐阅读
- angular - 由于超时,加载块 77 失败,但在 Sentry 上报告错误
- c# - for循环内对数据库的异步调用
- r - 自动设置 ggplot 边距以包含 geom_text
- python - 为什么我在 Code jam 2018 “再次拯救世界”中的回答是错误的?
- python - python如何连接两个字典
- ruby-on-rails - Ruby on Rails:如何使用 AWS Cognito 池以用户身份访问 S3?
- javascript - 如何在 VUE 组件的 Scoped 区域中使用 JSON 数据
- java - io.github.dropwizard-jobs 的 Maven 依赖项
- cuda - 函数名称中“i”的含义`cusparse
axpyi` 和 `cusparse 多蒂` - java - 单元测试,Debug 和 Run 模式下的 Mock 对象