我正在建模一个将使用JavaFX的原型。
该应用程序与自助服务终端类似,用于自助服务。但是在客户端与之交互之前,管理员应该将其解锁。管理员可以通过专用通道(HTTP或IPC或USB设备)发送一些远程命令。命令的示例包括:启动,停止和重置
我该怎么办?
a)我可以有一个任务,在另一个主动集中IPC的线程中运行,如果有消息,切换场景?
b)让一个反应器在一个线程中运行并且很快收到命令,它将它传递给JavaFX线程。
这两个选项都有效吗?确实存在第三个?
答案 0 :(得分:1)
您的选项(a)具有Task的线程和(b)没有任务的线程都是有效的。
推荐的解决方案
我选择选项b(没有任务的线程)。
解决方案的关键部分是:
Platform.runLater(() -> MyApplication.changeScene(newData));
任务很好,但可能不适合您的情况
如果你有一些由UI或JavaFX线程启动的东西,那么任务就很好。例如,用户单击一个按钮,您希望根据该操作从服务器检索数据,在检索数据时通过消息和进度条更新反馈进度报告。因此,Task非常适合这种操作,因为它明确支持诸如消息反馈和进度更新之类的事情,以及任务开始和完成时定义良好的状态模型。请参阅不变量代码示例,以了解Task如何改进此类情况:Platform.runLater and Task in JavaFX。
但是,当事件的发起者不在JavaFX应用程序线程中时,使用Task而不是使用传统的并发实用程序没有太大的优势。这是因为您通常不需要Task提供的额外服务,例如进度和消息更新API及其状态机。此外,启动此类事件的库通常已经拥有自己的线程模型设置,因此您不需要Task提供的额外线程框架。
使用Platform.runLater()
你真正想要的只是发生事情的通知。现在需要在JavaFX应用程序线程上进行通知,因为您无法使用另一个线程操纵活动场景中的项目。要将事件传递给JavaFX应用程序线程,请使用Platform.runLater(runnable)构造。
示例代码
我不会写Ruby,因为我真的不能,但是这里有一些Java代码可以为你提供要点 - 它实际上非常简单。
class DataReader implements Runnable {
private final DataSource dataSource;
public DataReader(String location) {
dataSource = new DataSource(location);
Thread thread = new Thread(this);
thread.setDaemon(false);
thread.start();
}
public void run() {
while (dataSource.hasData()) {
MyImmutableObject newData = dataSource.getSomeData();
Platform.runLater(() -> MyApplication.changeScene(newData));
}
}
}
class MyApplication extends Application {
public void changeScene(MyImmutableObject newData) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"layout.fxml"
)
);
UIController controller =
loader.<UIController>getController();
controller.initData(newData);
Scene scene = new Scene((Pane) loader.load());
stage.setScene(newScene);
}
}
上面的示例使用了虚构的DataSource,MyImmutableObject和UIController类以及虚构的FXML模板来演示这个概念(因此代码片段不是一个独立的可运行的东西)。 FXML加载概念来自:Passing Parameters JavaFX FXML。示例代码创建了自己的线程,但是如果您使用的库已经创建了线程(很可能),您不需要创建另一个线程,您可以使用Platform将适当的钩子添加到现有库中.runLater调用以获取事件通知以及在库线程和JavaFX应用程序之间传递数据。
相关问题
关于Platform.runLater与StackOverflow上的任务有很多其他问题:
其他问题
在我的情况下,管理员在某些情况下能够向信息亭发送初始信息,几乎就像(初始化矢量),例如护照号码。有了这些信息,仍然是Platform.runLater的最佳解决方案吗?
是的,Platform.runLater仍然是最好的解决方案。当管理员将信息发送到信息亭时(例如,嵌入式http服务器或jax-rs服务上的servlet),您将有一些线程被警告,并且它可以调用Platform.runLater来更新基于JavaFX的信息亭UI。资讯