【问题标题】:Swing timer alternative for JavaFX and the thread management differenceJavaFX 的 Swing 计时器替代方案和线程管理差异
【发布时间】:2014-04-24 14:31:07
【问题描述】:

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

事实上,我很想知道 Swing TimerSwingUtilities.invokeLater()invodeAndWait() 对于 JavaFX 的等价物。

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

【问题讨论】:

  • 不是重复的。我以前见过!解决方案和答案都不匹配。首先,我在谈论一个真正的计时器,而不是想要他/她的东西。另一方面,他们的例子是 Swing。答案对我来说不是一个好答案,它只在 TimerTask 中调用了 swing invokeLater!我问过我们应该使用什么,尽管 JavaFX 中有 SwingUtilities。我在问JavaFX中的线程管理...!

标签: multithreading swing timer javafx javafx-8


【解决方案1】:

JavaFX 等效于 SwingUtilities.invokeLater()

Platform.runLater(java.lang.Runnable runnable)

另见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.

另见Return result from javafx platform runlater

JavaFX 等效于 javax.swing.Timer

使用Timeline。以下将更新一个显示日期的标签每秒:

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();

另请参阅How to update the label box every 2 seconds in java fx? 的基于时间线的答复。

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

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

为了近似这一点,我建议只使用普通的java.util.Timer,而不是javax.swing.Timer,或者如果您需要更大的灵活性,请使用ScheduledExectorService。然后,在TimerTask 或预定Runnable 中,执行您的处理逻辑,并在处理完成后分别调用 Platform.runLater SwingUtilities.invokeLater 以将结果分流回任一JavaFX 或 Swing 组件。

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

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

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

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

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

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

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

参考文档

Concurrency in JavaFX Tutorial 来自 Oracle。特别是,请参阅 TaskService 中有关管理 JavaFX 后台操作的部分,本答案中未明确讨论的主题。

【讨论】:

    猜你喜欢
    • 2020-07-22
    • 2017-12-13
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    相关资源
    最近更新 更多