Listing 1 is a simple example of using
this class. Let’s work through the details,
because some things aren't obvious.
In line 8, we instantiate a JFXPanel object, but initially we tell it nothing about
what it will contain. That information
will be provided later. This component
can be added to a Swing Container just
as any other Swing component.
To understand how we encapsulate
the JavaFX scene, we need some details
about threads in Swing and JavaFX.
Swing uses a single event dispatch thread
(EDT), and JavaFX uses an application
thread. Both effectively do the same
thing, which is to process asynchronous
events that affect the UI (for example,
button presses, updates to displayed
values, window resizing, and so on).
As a Swing component, the JFXPanel
object must be accessed only from the
Swing EDT. The only exception to this is
the setScene() method, which must be
accessed from the JavaFX application
thread.
In order to set the scene for the
JFXPanel object, we must create another
object that implements the Runnable interface, which can then be posted to the
event queue and executed at some (
unspecified) time in the future. We use the
static utility method, runLater(), provided
in the Platform utility class, and then an
anonymous inner class to instantiate the
Runnable object. Due to the inner class
restrictions, the reference to the JFXPanel
must be made final.
The initFXComponent() method is
where the real JavaFX work happens.
Because JavaFX uses a scene graph, we
need to create a Scene object to hold the
parent node reference. When we instan-
tiate this object, we can also set the size
of the scene in pixels, which will then
be used by the Swing layout manager to
position the JavaFX component. We also
set the root node of the scene to be the
graph of objects that will be displayed.
1 public void init() {
2 setSize(300, 200);
3 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
4 setLayout(new BorderLayout());
5
6 /* Put the JavaFX scene in the middle */
7 fxComponent = new SimpleFXComponent(this);
8 final JFXPanel fxPanel = new JFXPanel();
9 add("Center", fxPanel);
10
11 /* Construct the JavaFX scene on its own application thread */
12 Platform.runLater(new Runnable() {
13 @Override
14 public void run() {
15 Scene scene = new Scene(fxComponent, 200, 100);
16 scene.setFill(Color.BLUEVIOLET);
17 fxPanel.setScene(scene);
18 }
19 });
20
21 /* Put the Swing button at the bottom */
22 changeButton = new JButton("Change JavaFX Button");
23
24...
25
26 add("South", changeButton);
27 setVisible(true);
28 }
COMMUNITY
JAVA IN ACTION
Swing and JavaFX Events
There is one more basic part of Swing
and JavaFX integration that needs to be
addressed, which is how the components interact when a Swing component
triggers a change in a JavaFX scene or
vice versa. If the JavaFX scene wants to
interact with Swing components, the
code must be wrapped in a Runnable
object and placed on the EDT using the
SwingUtilities.invokeLater() method, as
shown in Listing 2.
For the opposite case, where a Swing
component needs to interact with a
JavaFX scene, the code must again be
wrapped in a Runnable object, but this
time it must be placed on the JavaFX
application thread using the Platform
.runLater() method, as shown in Listing 3.
ABOUT US
See all listings as text
only a few more lines of code than
using a normal Swing component.
Having the JavaFX scene and Swing
components interact is also straightforward. You just have to remember to
wrap the necessary code in a Runnable
object and place it on the correct
queue for execution.
In the next article, we’ll take this
knowledge and start to modify our Swing
application to add exciting new
components that are created using
JavaFX. </article>
LEARN MORE
•;Documentation and tutorials
•;API documentation (Javadoc)
•;JavaFX Showcase
blog
Conclusion
So far, we’ve seen that adding a JavaFX
scene to a Swing container requires