且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JavaFX的Swing Timer替代品与线程管理的区别

更新时间:2023-12-03 23:36:46

等效于SwingUtilities.invokeLater()

Platform.runLater(java.lang.Runnable runnable)

另请参见 JavaFx对SwingUtilities.invokeLater的响应.

等效于invokeAndWait()

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

The public JavaFX API deliberately does not expose an invokeAndWait call on Platform.runLater because it is easy to deadlock yourself with it, so you can use the below code instead as long as you know exactly what you are doing.

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返回的结果.

等效于javax.swing.Timer的JavaFX.

JavaFX equivalent of javax.swing.Timer.

使用时间轴.以下内容将更新显示每秒日期的标签:

Use a Timeline. The following will update a label displaying the date every second:

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秒更新标签框?. >

See also the Timeline based answer to How to update the label box every 2 seconds in java fx?.

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

If we use some Swing components in the JavaFX? Should we use two parallel Timer/Threads for updating those components?

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

I think not, depends on the app, but generally a single Timer for the application would be preferred. This is kind of a specialized case. Generally, if you have some asynchronous process happening on a Timer, you want it to happen all at once, so the Timer fires, does some processing, then shunts the results back to the GUI. As you are mixing two UI frameworks, it's a little more complicated because you want to update both frameworks with results at the same time or within the same render frame.

要对此进行近似,我建议仅使用普通的 javax.swing.Timer ,或使用 ScheduledExectorService (如果您需要更大的灵活性).然后,在 TimerTask 或预定的可运行,然后执行处理逻辑处理完成后,分别调用Platform.runLater 和单独的 SwingUtilities.invokeLater,以将结果分流回JavaFX或Swing组件.

To approximate this, I'd advise using just a plain java.util.Timer, rather than a javax.swing.Timer, or use a ScheduledExectorService if you need more flexibility. Then, in the TimerTask or scheduled Runnable, perform your processing logic and after the processing is done make calls to Platform.runLater and seperately SwingUtilities.invokeLater as appropriate to shunt the results back to either JavaFX or Swing components.

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

Of course you should consider if mixing two frameworks such as this and dealing with the potential threading complications is worth it. If you are able to just use a single framework and rely on the concurrency approach which works best with that framework, I think that would be a preferred approach.

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

What is the difference of the thread management between JavaFX and Swing?

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

From a user point of view it is pretty similar. Both JavaFX and Swing remain single threaded frameworks for application layer UI processing. All user code for JavaFX runs on the JavaFX application thread. Moreover any code which may modify the active scene graph (nodes displayed on the stage), must run on the JavaFX application thread. These rules are similar to the nature of thread management in Swing programming.

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

The JavaFX application thread and the Swing thread in the initial release of Java 8 are different by default. So:

  1. 要从JavaFX应用程序线程更新Swing组件,请使用Platform.runLater将处理从JavaFX线程切换到Swing线程.
  2. 要从Swing线程更新JavaFX节点,请使用SwingUtilities.invokeLater将处理从Swing线程切换到JavaFX线程.
  1. To update Swing components from the JavaFX application thread, use Platform.runLater to switch processing from the JavaFX thread to the Swing thread.
  2. To update JavaFX nodes from the Swing thread, use SwingUtilities.invokeLater to switch processing from the Swing thread to the JavaFX thread.

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

A future release of the Java platform may feature a unified application thread for Swing and JavaFX.

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

Note that the internal threading implementation used in library code differs between Swing and JavaFX. JavaFX will use different hardware and software rendering pipelines which can run on their own thread. However, this internal implementation detail is completely hidden from the application programmer.

参考文档

JavaFX教程中的并发.特别是,请参见任务和服务未在此答案中明确讨论.

Concurrency in JavaFX Tutorial by Oracle. In particular, see the sections on Task and Service for managing background operations from JavaFX, topics which are not explicitly discussed in this answer.