java - 在某些外部事件后切换 javafx/jrubyfx 场景

标签 java javafx jruby

我正在建模一个将使用 JavaFX 的原型(prototype)。

该应用程序将与自助服务终端类似。然而,在客户端与其交互之前,管理员应该将其解锁。管理员将能够通过专用 channel (HTTP 或 IPC 或 USB 设备)发送一些远程命令。命令示例为:启动、停止和重置

我该怎么做?

a) 我可以有一个任务,在另一个线程池中主动运行 IPC,如果那里有消息,则切换场景?

b) 让 react 器在线程中运行,一旦收到命令,就会将其传递给 JavaFX 线程。

这两个选项都有效吗?是否存在第三个?

最佳答案

您的两个选项 (a) 都与 Task 相连(b) 没有任务的线程有效。

推荐解决方案

我会选择选项 b(没有任务的线程)。

解决方案的关键部分是以下行:

Platform.runLater(() -> MyApplication.changeScene(newData));

任务很好,但可能不是最适合您的情况

如果您有由 UI 或 JavaFX 线程启动的任务,那么任务就很好。例如,用户单击按钮,您希望根据该操作从服务器检索数据,通过消息反馈进度报告,并在检索数据时更新进度栏。因此,Task 非常适合此类操作,因为它对消息反馈和进度更新等内容有明确的支持,以及任务启动和完成时定义良好的状态模型。请参阅不变量代码示例以了解 Task 如何改进此类情况:Platform.runLater and Task in JavaFX .

但是,当事件的发起者脱离 JavaFX 应用程序线程时,与仅使用传统并发实用程序相比,使用任务并没有太大优势。这是因为您通常不需要任务提供的额外服务,例如进度和消息更新 API 及其状态机。此外,启动此类事件的库通常已经有自己的线程模型设置,因此您不需要任务提供的额外线程框架。

使用 Platform.runLater()

您真正想要的只是收到发生某事的通知。现在,通知需要在 JavaFX 应用程序线程上发生,因为您无法使用另一个线程操作 Activity 场景中的项目。要获取传递到 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 调用将适当的 Hook 添加到现有库中即可获取事件通知并在库线程和 JavaFX 应用程序之间传递数据。

相关问题

关于 Platform.runLater 与 StackOverflow 上的任务还有许多其他问题:

其他问题

in my case, the administrator will be able, in some cases, to send an initial information to the kiosk, almost like an (initialization vector), for example the passport number. With this information, still the Platform.runLater the best solution?

是的,Platform.runLater 仍然是最好的解决方案。当管理员将信息发送到信息亭(例如嵌入式 http 服务器上的 servlet 或 jax-rs 服务)时,您将有一些线程收到警报,并且它可以调用 Platform.runLater 以根据该信息更新基于 JavaFX 的信息亭 UI。

关于java - 在某些外部事件后切换 javafx/jrubyfx 场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26823040/

相关文章:

java - Eclipse 在 println 方法上给出错误

JavaFX 在 FXML 中定义内部类

java - JRuby 中的应用程序开发

ruby - 从MRI切换到JRuby有任何陷阱吗?

java - 由 tomcat7 暂停产生的进程

java - 数组内存初始化背后的概念是什么?

java - 俄罗斯方 block 已停止工作

java - BinaryRelation接口(interface)

JavaFX 新场景或新 Pane

JavaFX - 迭代每行 GridPane 节点 - 读取每行 GridPane 节点