Both your options (a) thread with Task and (b) thread without task are valid.
Recommended Solution
I'd choose option b (thread without a task).
The key part of the solution is the line:
Platform.runLater(() -> MyApplication.changeScene(newData));
Task is good, but probably not best for your situation
Task is good if you have something which is initiated by the UI or JavaFX thread. For example, the user clicks a button and you want to retrieve data from a server based upon that action, feeding back progress reports via messages and progress bar updates as the data is retrieved. So Task is very good for that kind of operation because it has explicit support for things such as the message feedback and progress updates as well as a well defined state model for when the task starts and completes. See invariants code example to understand how Task improves such situations: Platform.runLater and Task in JavaFX.
However, when the initiator of the event is off the JavaFX application thread, there isn't much advantage in using a Task versus just using traditional concurrency utilities. This is because you typically don't need the extra services that the Task is providing such as the progress and message update APIs and its state machine. Also, libraries that are initiating such events typically already have their own thread model setup, so you don't need the extra threading framework provided by a Task.
Using Platform.runLater()
All you really want is a notification that something happened. Now that notification needs to occur on the JavaFX application thread as you can't manipulate items in an active scene using another thread. To get an event passed to the JavaFX application thread, you use the Platform.runLater(runnable) construct.
Sample Code
I won't write Ruby, because I really can't, but here is some code in Java to give you the gist - it's actually really simple.
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);
}
}
The above sample makes use of fictional DataSource, MyImmutableObject and UIController classes and a fictional FXML template to demonstrate the concept (so the snippet is not a standalone runnable thing). The FXML loading concepts come from: Passing Parameters JavaFX FXML. The sample code creates its own thread, but if whatever you library you are using already creates threads itself (which is likely), you don't need to create another one, you can just add appropriate hooks into the existing library with Platform.runLater calls to get the event notification and passing of data between the library threads and your JavaFX application.
Related Questions
There are numerous other questions on Platform.runLater versus Task on StackOverflow:
Additional Questions
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?
Yes, Platform.runLater is still the best solution. You will have some thread which is alerted when the administrator sends the information to the kiosk (e.g. a servlet on an embedded http server or a jax-rs service) and it can invoke Platform.runLater to update the JavaFX based kiosk UI based on that info.