Channels ▼

Eric Bruno

Dr. Dobb's Bloggers

Integrating JavaFX 2.x and Swing: It's Simple

August 24, 2012

With JavaFX 1.x, it was possible to embed Swing controls into a JavaFX application, but officially it wasn't possible to do the reverse. Although Sun/Oracle didn't support it, clever people found a way around this (read my past writing on the subject if you're interested). However, it quickly became evident that many people had large, complex Swing applications that they weren't willing or capable of entirely refactoring as a JavaFX application. So, Oracle added the ability to embed JavaFX components (built-in controls, custom controls, as well as entire JavaFX Scenes) inside a Swing application. With the JavaFX 2.x JFXPanel class, the one class needed to accomplish this, you can host JavaFX components alongside Swing components within a Swing JPanel, for instance. Let's look at how this works conceptually:

Containment model:

JPanel <- JFXPanel <- Scene <- Group <- javafx.control.*

Or, in pseudocode:

JPanel.add(JFXPanel.setScene(Scene.setRoot(Group.getChildren().add( javafx.control ))));

That may look complicated, but it's really not. You set up the JavaFX Scene relationship as usual, with no need for a Stage since the Swing application will act as your stage. Instead, create your JavaFX container (HBox, VBox, or Group, and so on), set it as your Scene's Root (or Parent), then add JavaFX controls to that root container. Finally, add the Scene to a special JFXPanel class, whose only role in life is to be placed within a Swing container (i.e., a JPanel) and serve as a bridge between the two worlds — a wormhole, if you will. Voila… Swing/JavaFX integration in a nutshell.

A Working Example

As an example, let's take the really cool SizeView container I created with JavaFX 2.x a few months ago. This custom container allows you to place any number of JavaFX controls within it, where each are separated by a sizing bar. When you resize one component, the others adjacent to it resize accordingly. Learn all about the control and resizing algorithms from my past blog.

The code is below. The explanation is this:

  1. The Swing application starts
  2. A JFrame is created and sized
  3. The SwingFX2 class (which extends JPanel) is instantiated and added to the JFrame
  4. In the constructor, initComponents is called, where the following steps occur:
    – A JFXPanel is created and added to the JPanel
    – A Swing JButton is created and added to the JPanel
    – A Scene is created and provided a parent container (Group)
    – A JavaFX Control is created and added to the root container
    – The scene is added to the JFXPanel
    – Everything is made visible

The application, when run, looks like this:

Screenshot

For the official Oracle tutorial on the JFXPanel class, go here.

Happy Coding!
-EJB


public class SwingFX2 extends JPanel {  // It's a Swing JPanel
    private JFXPanel jfxPanel;          // The JavaFX component(s)
    private JButton swingButton;        // The Swing component

    public SwingFX2(){  
        initComponents();  
    }  
  
    public static void main(String ...args){  
        SwingUtilities.invokeLater(new Runnable() {  
            public void run() {  
                // Create a Swing Frame
                final JFrame frame = new JFrame();  
                frame.setMinimumSize(new Dimension(640, 480));  
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
                 
                // Add the Swing JPanel and make visible
                frame.getContentPane().add(new SwingFX2());  
                frame.setVisible(true);  
            }  
        });     
    }  
     
    private void initComponents(){ 
        // The JavaFX 2.x JFXPanel makes the Swing integration seamless
        jfxPanel = new JFXPanel();  

        // Create the JavaFX Scene
        createScene();  
         
        setLayout(new BorderLayout());  
        add(jfxPanel, BorderLayout.CENTER);  
         
        swingButton = new JButton();  
        swingButton.addActionListener(
            new ActionListener() {  
                @Override
                public void actionPerformed(java.awt.event.ActionEvent ae) {
                    System.exit(0);
                }
            });  
        
        swingButton.setText("Close");  
         
        add(swingButton, BorderLayout.SOUTH);  
    }     
     
    private void createScene() {  
        // The Scene needs to be created on "FX user thread", NOT on the 
        // AWT Event Thread 
        PlatformImpl.startup(
            new Runnable() {
                public void run() {  
                    Group root = new Group();  
                    Scene scene = new Scene(root, 80, 20);  
                    SizeView sizeview = createSizeView(scene);
                    root.getChildren().add(sizeview);
                    jfxPanel.setScene(scene);  
                }  
            });  
    }     

    private SizeView createSizeView(Scene scene) { 
        double HBOX_WIDTH = scene.getWidth() - 10 - 10;

        final SizeView sizeview = new SizeView();
        sizeview.setLayoutX(10);
        sizeview.setLayoutY(10);
        sizeview.setPrefWidth(HBOX_WIDTH);
        
        Node[] controls = new Node[5];
        for ( int l = 0; l < controls.length; l++ ) {
            controls[l] = new ListView();
        }

        sizeview.getChildren().setAll(controls);
        
        scene.widthProperty().addListener(
            new ChangeListener() {
                public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                    Double w = (Double)newValue;
                    sizeview.setPrefWidth( w - 20 );
                    sizeview.layout();
                }
            });
        
        return sizeview;
    }
}

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Comments:



Video