Java FX modifying UI component state with/without using Platform.runLater - java

In java fx controller i have two version of the code that simply sets a text on a label when a button is pressed (this is just a sample, but any other ui modification can be considered)...
first version uses Platform.runLater :
Platform.runLater(() -> {
status.setText("");
statusIndicator.setVisible(false);
});
the other one simply modifies it in ordinary thread :
status.setText("");
statusIndicator.setVisible(false);
Both are working perfectly fine, only difference i know so far is that passing some runnable to Platform.runLater will keep the order of execution.
is there any other significat difference or motive to use Platform.runLater?

JavaFX has just a single UI thread
From Docs
The JavaFX scene graph, which represents the graphical user interface
of a JavaFX application, is not thread-safe and can only be accessed
and modified from the UI thread also known as the JavaFX Application
thread
In case you have long-running tasks, you will want to run them on background threads and after completion of such threads, you would want to update the result back to the UI. Under such scenario's, you use the updation surrounded with Platform.runlater(). Surrounding your code with Platform.runLater enables your code to communicate with the JavaFX Application thread.
Coming to your question :
is there any other significat difference or motive to use Platform.runLater?
I hope most of it is already answered, just to add
1 . You don't have to use Platform.runlater(), if you are already on the JavaFX Application thread
2 . As the Platform.runLater() doc says
Run the specified Runnable on the JavaFX Application Thread at some unspecified time in the future
We are not sure when the update will take place, it depends on the number of updates waiting to be processed. If a number of updates are waiting to be processed on the UI thread, it can take some time (such scenario normally doesn't happen)

Related

JavaFX: Can a node's tranforms be safely manipulated from a non-UI thread? [duplicate]

This question already has an answer here:
Update JavaFX Live nodes outside Application Thread
(1 answer)
Closed 3 years ago.
I've been working on a robot simulator using javafx. It uses a separate thread to calculate where the robot and each of its parts should be after each time increment. The actual updating of the UI is handled with a call to Platform.runLater().
Here is an example of how a node (in this case a Rectangle) called leftFinger would be manipulated:
First, in the Controller class, create a Translate object and add it to the node's transforms:
leftFingerTranslateTransform = new Translate(0, 0);
leftFinger.getTransforms().add(leftFingerTranslateTransform);
Then, in the method that is passed into Platform.runLater() do the following:
leftFingerTranslateTransform.setY(-40.0 * (armScale - 1.0));
leftFingerTranslateTransform.setX(fingerPos);
The above has worked well.
At one point, I accidentally put some of this node-repositioning code ( i.e., the calls to Tranlate.setX() and Translate.setY() ) into a method that is called by the non-UI thread, without a call to Platform.runLater(). To my surprise, this worked, with no problems. But I'm wondering if this could cause problems.
My searches for information about javafx and multithreading had led me to believe that the UI couldn't (or, at least shouldn't) be manipulated directly from a non-UI thread. Through experimentation, I've found that attempting to add a node to a scene from a non-UI thread causes an exception to be thrown, but manipulating (i.e., changing the properties of) a transform belonging to a node does not.
My question is: can the transforms belonging to a node safely have their properties changed from a non-UI thread (without using Platform.runLater())?
Changing transforms on the node from a non-UI thread, when the node is attached to an active scene, could cause issues such as race conditions.
Don’t do it.
Explanation
From Wikipedia on race conditions:
Race conditions arise in software when an application depends on the sequence or timing of processes or threads for it to operate properly. As with electronics, there are critical race conditions that result in invalid execution and bugs. Critical race conditions often happen when the processes or threads depend on some shared state. Operations upon shared states are critical sections that must be mutually exclusive. Failure to obey this rule opens up the possibility of corrupting the shared state.
Here, the shared state is the list of transforms and stuff which is derived from them (such as the layout of the scene).
From the Node Javadoc, as linked by Slaw in comments:
Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene in a Window that is showing. An application must attach nodes to such a Scene or modify them on the JavaFX Application Thread
The reason that it is unsafe is because the JavaFX UI thread runs on a timed pulse (see the JavaFX architecture doc to understand this), concurrently to any non-UI threads. During the timed pulse, the scene is rendered, CSS is applied, transforms are applied, animated properties are updated, etc. So if you modify the transforms on a non-UI thread while they are being applied during the pulse processing by the UI thread, you have a potential race condition, which can result in corrupted shared state, and the outcome is unpredictable and possibly quite undesirable.

JavaFX Timeline vs ScheduledExecutorService

In a JavaFX 8 project, you can use javafx.animation.Timeline like this:
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(250),
actionEvent -> {
updateTemperature();
}
)
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Or you can something very similar using a ScheduledExecutorService:
executorService.scheduleAtFixedRate(this::updateTemperature, 0, 250, TimeUnit.SECONDS);
Are there any "best practises" for using one over the other?
As with most UI toolkits, in JavaFX you must not access UI components that are part of the display from any thread other than the dedicated UI thread (the FX Application Thread in the case of JavaFX). Additionally, code that takes (or may take) time to run (e.g. has blocking calls, as with I/O or networking) should not be executed on the UI thread as it will make the UI unresponsive.
The two code snippets you posted are quite different with regard to threading. The ScheduledExecutor will execute updateTemperature() on a background thread (i.e. not the FX Application Thread). This is appropriate if updateTemperature() takes a long time to run; but it will likely throw an exception (or, worse, have the potential of leaving the UI in an inconsistent state) if it accesses the UI.
By contrast, the Timeline creates no new threads and executes updateTemperature() on the FX Application Thread. If updateTemperature() accesses the UI, it must be performed on this thread and this is a convenient way to do so. If it takes a long time to run (which I assume it doesn't, since you're calling it 4 times per second), it will have the effect of making the UI unresponsive.

Verify code is running on user-interface thread in Vaadin 7 app

Is there some way to verify that code is executing on the user’s user interface thread (event loop thread)?
This question is the Vaadin equivalent of this question, Swing verify code on Event Dispatch Thread at runtime.
I know how to call UI::access from a background thread to schedule a Runnable to be run on the user-interface thread. My question is how to double-check that some executing code is indeed running on the user-interface thread.
I filed a feature request for this.
UI.getCurrent()
If UI.getCurrent() returns an instance you are (most probably) either:
On a thread started by UI interaction
On a thread that is already initiated with UI::access
To quote the Vaadin 7.3.9 doc:
… In other cases, (e.g. from background threads), the current UI is not automatically defined.
Example Code
boolean uiOrUiAccessManagedThread = UI.getCurrent() != null;
The framework is already full of asserts in various code paths that should only be run on the thread that has locked the UI state. The most important being whenever shared state is accessed.
To benefit from this checking, just make sure your server is run with assertion checking enabled, i.e. by starting it with the -ea JVM parameter.

EventQueue.invokeLater in Java Swing

I am trying to understand the real purpose of this thread.
I have read books , articles ,but didn't undrstand clearly what EventQueue thread is responsible for. I have seen a lot of examples, sometimes this is used, sometimes not. As I understood this thread is responsible for ALL GUI OPERATIONS, such creating windows, components, calling native functions from OS API and other stuff. So every time I change some part of GUI I should pass this action to queue.
So using queue application has two threads by default main and event dispatching thread. So I all bussines logic should be performed in main thread (or create new thread from main) and all gui operations in EventQueue(for example adding new item to the table, changing text in label updating list). Futhermore I should create instance of main windows (class extends jframe) in EventQueue ?
Am I right ? If not please explain. Thanks everyone in advance.
EventQueue manages a single GUI thread because it must rely on the host platform's GUI resources, which are also single-threaded. You can run non-GUI code on the initial thread, but you must synchronize access to any shared data yourself. SwingWorker, examined here, is a convenient alternative.
It sounds like you've got the gist of it, yes. If your application is essentially "pure GUI" you can just do everything on the EDT (Event Dispatch Thread, which is the thread that runs whatever you pass to EventQueue.invokeLater), but you must create windows on the EDT which means your main() method must use EventQueue.invokeLater at least once.
Because all listeners on GUI objects will be notified on the EDT, you do not need use EventQueue.invokeLater from your handlers, generally.

JavaFX 2: background and Platform.runLater vs Task/Service

I'm pretty confused about the concept of Task/Service in JavaFX.
I have used a model based on a background thread for my background work, which call Platform.runLater for any update to the UI.
Let's say I'm not interested in a progress bar or such. I'm doing some real work on my model that must be updated in the view of the GUI (e.g a list of participants which updates over time based on some connection in the background, list of participant based on some user input, classified by age and origin). This is what I usually achieve with background threads that I start, and within which I use Platform.runLater.
Now in JavaFX 2 they have all this concurrency using Tasks and Services, suggesting that it is better to use them. But I don't see any examples that achieve what I'm talking about.
Updating the progress bar by binding some properties is nice (but those are information on the task not your model).
So, how can I actually update the content of my views based on my model? Should I call Platform.runLater from within the Task? If not, what is the mechanism? How do I catch when the tasks have succeed and get the result (the update of the actual model) to update the view?
The tutorials by Oracle unfortunately were not very good in this regard. Pointing me to some good tutorials would also help.
The Task and Service classes are designed to encourage good practice and proper use of concurrency for some (but not all) common scenarios in GUI programming.
A typical scenario is that the application needs to execute some logic in response to a user action which may take a long time (maybe a long calculation, or, more commonly, a database lookup). The process will return a result which is then used to update the UI. As you know, the long-running process needs to be executed on a background thread to keep the UI responsive, and the update to the UI must be executed on the FX Application Thread.
The Task class provides an abstraction for this kind of functionality, and represents a "one-off" task that is executed and produces a result. The call() method will be executed on the background thread, and is designed to return the result of the process, and there are event listeners for when the task completes that are notified on the FX Application thread. The developer is strongly encouraged to initialize the Task implementation with immutable state and have the call() method return an immutable object, which guarantees proper synchronization between the background thread and the FX Application Thread.
There are additional common requirements on these kinds of tasks, such as updating a message or the progress as the task progresses. The application may also need to monitor the life-cycle state of the class (waiting to run, running, completed, failed with an exception, etc). Programming this correctly is quite subtly difficult, as it necessarily involves accessing mutable state in two different threads, and there are many application developers who are unaware of the subtleties. The Task class provides simple hooks for this kind of functionality and takes care of all the synchronization.
To use this functionality, just create a Task whose call() method returns the result of your computation, register a handler for when the state transitions from RUNNING to SUCCEEDED, and run the task in a background thread:
final Task<MyDataType> task = new Task<MyDataType>() {
#Override
public MyDataType call() throws Exception {
// do work here...
return result ;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
MyDataType result = task.getValue(); // result of computation
// update UI with result
}
});
Thread t = new Thread(task);
t.setDaemon(true); // thread will not prevent application shutdown
t.start();
The way this works behind the scenes is that the Task maintains a state property, which is implemented using a regular JavaFX ObjectProperty. The Task itself is wrapped in a private implementation of Callable, and the Callable implementation is the object passed to the superclass constructor. Consequently, the Callable's call() method is actually the method executed in the background thread. The Callable's call() method is implemented as follows:
Schedule a call on the FX Application thread (i.e. using Platform.runLater()) that updates the state, first to SCHEDULED, then to RUNNING
Invoke the call() method of the Task (i.e. the user-developed call() method)
Schedule a call on the FX Application Thread that updates the value property to the result of the call() method
Schedule a call on the FX Application Thread that updates the state property to SUCCEEDED
This last step will of course invoke listeners registered with the state property, and since the state change was invoked on the FX Application Thread, so to will those listeners' handle() methods.
For a full understanding of how this works, see the source code.
Commonly, the application may want to execute these tasks multiple discrete times, and monitor the current state representing all of the processes (i.e. "running" now means one instance is running, etc). The Service class simply provides a wrapper for this via a createTask() method. When the Service is started, it gets a Task instance by calling createTask(), executes it via its Executor, and transitions its own state accordingly.
There are of course many concurrency use cases that don't fit (at least cleanly) into the Task or Service implementations. If you have a single background Thread that is running for the entire duration of your application (so it represents a continuous process, rather than a one-off task), then the Task class is not a good fit. Examples of this might include a game loop, or (perhaps) polling. In these cases you may well be better off using your own Thread with Platform.runLater() to update the UI, but of course you have to handle proper synchronization of any variables that may be accessed by both threads. In my experience, it is worth spending some time thinking about whether these requirements can be re-organized into something that does fit into the Task or Service model, as if this can be done the resulting code structure is often much cleaner and easier to manage. There are certainly cases where this is not the case, however, in which case using a Thread and Platform.runLater() is appropriate.
One last comment on polling (or any other requirement for a periodically-scheduled background task). The Service class looks like a good candidate for this, but it turns out to be quite hard to manage the periodicity effectively. JavaFX 8 introduced a ScheduledService class which takes care of this functionality quite nicely, and also adds handling for cases such as repeated failure of the background task.

Categories

Resources