如何在线程和GUI之间进行通信

时间:2019-12-17 17:19:19

标签: java multithreading kotlin javafx

当前,我正在使用Kotlin和Java开发桌面应用程序,GUI是使用JavaFX制作的。 我有几个基本的UDP服务器(Kotlin线程)正在侦听不同的端口,以通过网络接收数据。连接工作正常。

我可以想到几种(或多或少复杂的)线程与GUI控制器之间的通信方式,但是我想知道是否存在某种默认方法,我只是不知道

我正在寻找一种简单的方法,可以将“消息”从线程发送到控制器,以便更改标签上的某些文本或类似内容。

1 个答案:

答案 0 :(得分:2)

使用Platform.runLater

不在JavaFX线程上时,请使用Platform.runLater调用最终将更新GUI的方法。

这样做将安排包装在runLater中的代码,以便稍后在JavaFX应用程序线程上执行。

由于JavaFX系统被设计为单线程系统,因此有必要使该系统一致地工作。

JavaFX中的更高级别的并发支持

JavaFX还使用higher level concurrency support之类的东西Task,这些东西通过诸如updateMessage之类的方法具有一定的通信支持。在Task的实现级别上,updateMessage仅在内部使用Platform.runLater,但在实现中包括一些其他优化措施,以使其使用起来简单高效。

通常,Tasks和Platform.runLater具有不同的重点(有时是互补的),请参阅Javafx: Difference between javafx.concurent and Platform.runLater?

特别是,对于需要UDP服务器侦听多个端口并将信息反馈给GUI的要求,与使用JavaFX Task相比,直接调用runLater是更合适的解决方案。

其他问题的答案

  

但是对于我而言,绑定可能有效

在未将调用包装在Platform.runLater调用中的情况下,请勿使用绑定,修改属性或从另一个线程触发更改侦听器。

绑定和更改侦听器并非旨在在多线程环境中工作(例如,如果您同时修改绑定或更改不同线程上的侦听器,则结果可能无法预测)。另外,如果您的绑定或更改侦听器最终触发了JavaFX应用程序线程对活动场景图的更改,那么结果可能又是不可预测的,因为场景图并非旨在以这种方式使用。

  

由于我无法从线程类访问相关的GUI元素,因此目前我不知道如何使用runLater()。

一些不同的选项:

  1. 为线程类提供对GUI元素的访问,因此它可以在runLater调用中进行修改(这是您的设计修改),或者
  2. 让线程类调用另一个类的方法(通过runLater),该类确实了解GUI元素,并且可以进行适当的更改,或者
  3. 使用具有可观察属性的共享模型类,您已将其附加到已建立绑定或更改侦听器的控制器类上,以基于对属性的更改来更新UI。在您的线程中,您应该read(请参阅链接,以了解从GUI线程到另一个线程的通信方式),并使用runLater将可观察的属性写入共享模型类。

如您所见,在所有情况下,最终runLater都用于安排涉及GUI的工作,该工作稍后将在JavaFX线程上运行,以在系统内实施线程安全。而且在所有情况下,如果您无法直接访问GUI元素,则需要与进行通信的对象进行通信,以便它可以代表您进行任何必要的修改。