Practitioners of JavaFX can easily abuse its ease of use to create applications that perform and scale poorly. This section provides a list of some practices that should help you avoid performance or usability penalties.
Declare your variables using the def keyword always use the
def
keyword to declare your variable, unless you know for certain that the variable will be updated later or is a bound variable.Stay off the EDT JavaFX applications are inherently single-threaded running on one special thread called the Event Dispatch Thread (EDT). All GUI activities are handled on the EDT. If you execute long-running processes directly in your JavaFX code, they will degrade the responsiveness of the UI or make it outright unusable. JavaFX offers the Task API, which is designed to provide the mechanism to execute processes asynchronously.
You can do this in three steps:
1. Create a Java class that implements
javafx.async.RunnableFuture
and overrides therun()
method, which contains the asynchronous code that you want to run:public class LongRunningRunnable implements RunnableFuture{ private long limit = Long.MAX_VALUE; public LongRunningRunnable(long l){limit = l;} // constructor public void run() throws Exception { for(int i = 0; i < limit; i++){ Thread.currentThread().sleep(200); } } }
2. Next, create a JavaFX class that extends
javafx.aysync.JavaTaskBase
and overridesfunction create():RunnableFuture
, which returns an instance of the newly-defined Java class above to be executed in its own thread:public class LongRunningTask extends JavaTaskBase{ public-init var limit = Long.MAX_VALUE; override protected function create () : RunnableFuture { new LongRunningRunnable(limit); } }
3. Lastly, use the JavaFX class (defined above) to start your long-running process on its own thread:
var t = LongRunningTask{limit:Byte.MAX_VALUE} JavaFXJavaFXdevelopment practicest.start(); // start task on its own thread
Reuse image objects - if you have an image that appears in multiple places, load the image once using the
Image
object, then reuse theImage
instance in any image number ofImageView
instances. That way, you don’t have duplicated bytes wasting memory resources.Scale media to size - avoid using images or videos at larger resolutions than needed. When possible, encode your media to the size and resolution that you will actually need. This will avoid unnecessary scaling transformation penalties when scaled in JavaFX.
Turn off smooth - when your scene graph contains a large number of shapes, you can gain performance by setting the
smooth
property tofalse
in order to reduce the overhead required for anti-aliasing wherever possible.Cache your visual nodes - when the scene graph engine paints its node on the screen, you can avoid repaint penalties by caching complex non-rotated object graphs. Caching causes the engine to reuse previously rendered images, rather then repainting the scene every time.
Remove instead of hide - to keep your node rendering time down, and increase performance, you should delete objects from the scene graph instead of setting property
visible
tofalse
whenever possible.Avoid Gratuitous Effects and Animations - effects (paint, transformation, scale, and so on) and animations incur processing overhead, especially with large numbers of nodes. Avoid applying effects and animations unless absolutely necessary.
Ungroup paint effects - when your nodes are encapsulated in a
Group
instance, apply your effects to individual nodes instead of theGroup
node. This provides granular control of where the effects are applied and helps avoid necessary rendition of effects.Set timeline’s frame rate - when you are working with fairly complex animations, you can provide better directives for frames generated by specifying the
framerate
property. If not, the engine will attempt to determine the best frame rate value to achieve the animation, which can result in wasted frames being generated.Use binding sparingly - data binding is a useful and a killer feature in JavaFX. Just like anything else though, its unnecessary overuse can be troublesome. Improper or careless binding can lead to cascading triggers that causes unwanted performance degradation that are hard to find. Use data binding only when you understand the event path and values that are updated during binding update. In most cases, updating a variable directly by setting its value works better.