JavaFX 的 Swing 计时器替代方案以及线程管理差异

2024-04-29

使用 JavaFX 的 Swing 计时器是否安全,或者 Swing 有特殊的替代方案吗? JavaFX 和 Swing 的线程管理有什么区别?

事实上我很想知道相当于摇摆计时器, SwingUtilities.invokeLater() and invodeAndWait()对于 JavaFX。

顺便问一下,如果我们在 JavaFX 中使用一些 Swing 组件怎么办?我们应该使用两个并行的计时器/线程来更新这些组件吗?


JavaFX 相当于SwingUtilities.invokeLater()

Platform.runLater(java.lang.Runnable runnable)

也可以看看JavaFx 对 SwingUtilities.invokeLater 的响应 https://stackoverflow.com/questions/12984310/javafx-response-to-swingutilities-invokelater.

JavaFX 相当于invokeAndWait()

公共 JavaFX API 故意不在 Platform.runLater 上公开 invokeAndWait 调用,因为它很容易使您自己陷入僵局,因此只要您确切知道自己在做什么,就可以使用下面的代码。

final FutureTask query = new FutureTask(new Callable() {
    @Override
    public Object call() throws Exception {
        return queryPassword();
    }
});
Platform.runLater(query);
System.out.println(query.get()); // the get blocks until the query FutureTask completes.

也可以看看javafx平台runlater返回结果 https://stackoverflow.com/questions/13796595/return-result-from-javafx-platform-runlater.

JavaFX 相当于javax.swing.Timer.

Use a Timeline http://docs.oracle.com/javafx/2/api/javafx/animation/Timeline.html。以下代码将更新每秒显示日期的标签:

DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Label dateLabel = new Label();
Timeline timeline = new Timeline(
    new KeyFrame(
      Duration.ZERO,
      actionEvent -> dateLabel.set(dateFormat.format(new Date()))
    ),
    new KeyFrame(
      Duration.seconds(1)
    )
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();

另请参阅基于时间轴的答案如何在java fx中每2秒更新一次标签框? https://stackoverflow.com/a/16138351/1155209.

如果我们在JavaFX中使用一些Swing组件呢?我们应该使用两个并行的计时器/线程来更新这些组件吗?

我认为不是,取决于应用程序,但通常应用程序的单个计时器是首选。这是一个特殊的案例。通常,如果您在计时器上发生一些异步进程,您希望它同时发生,因此计时器会触发,进行一些处理,然后将结果分流回 GUI。当您混合两个 UI 框架时,情况会稍微复杂一些,因为您希望同时或在同一渲染帧内更新两个框架的结果。

为了近似这个,我建议只使用一个简单的java.util.Timer http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html,而不是一个javax.swing.Timer http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html,或使用预定执行服务 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html如果您需要更多灵活性。然后,在定时任务 http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html或预定的Runnable http://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html,执行您的处理逻辑,并在处理完成后调用 Platform.runLater并分别SwingUtilities.invokeLater 根据需要将结果分流回 JavaFX 或 Swing 组件。

当然,您应该考虑混合这样的两个框架并处理潜在的线程复杂性是否值得。如果您能够仅使用单个框架并依赖最适合该框架的并发方法,我认为这将是首选方法。

JavaFX 和 Swing 的线程管理有什么区别?

从用户的角度来看,它非常相似。 JavaFX 和 Swing 仍然是应用层 UI 处理的单线程框架。 JavaFX 的所有用户代码都在 JavaFX 应用程序线程上运行。此外,任何可能修改活动场景图(舞台上显示的节点)的代码都必须在 JavaFX 应用程序线程上运行。这些规则类似于 Swing 编程中线程管理的本质。

默认情况下,JavaFX 应用程序线程和 Java 8 初始版本中的 Swing 线程是不同的。所以:

  1. 要从 JavaFX 应用程序线程更新 Swing 组件,请使用Platform.runLater将处理从 JavaFX 线程切换到 Swing 线程。
  2. 要从 Swing 线程更新 JavaFX 节点,请使用SwingUtilities.invokeLater将处理从 Swing 线程切换到 JavaFX 线程。

Java 平台的未来版本可能会为 Swing 和 JavaFX 提供统一的应用程序线程。

请注意,Swing 和 JavaFX 库代码中使用的内部线程实现有所不同。 JavaFX 将使用不同的硬件和软件渲染管道,这些管道可以在自己的线程上运行。然而,这个内部实现细节对应用程序程序员是完全隐藏的。

参考文档

JavaFX 教程中的并发 http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm由甲骨文公司。特别是,请参阅有关Task http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html and Service http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html用于管理 JavaFX 的后台操作,本答案中未明确讨论的主题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaFX 的 Swing 计时器替代方案以及线程管理差异 的相关文章

随机推荐