Home » Java » Desktop Java » Swing and JavaFX: working with JFXPanel

About Jens Deters

Jens Deters
Jens Deters is a Senior Software Developer working in the domain of Aviation Authorities. His main objectives are RIA and Desktop Applications also he loves to play with IoT related stuff.

Swing and JavaFX: working with JFXPanel

I soon will have to deal with JavaFX in a Swing based fat client – oh sorry, of course I meant “multi-layered rich-client”!

So this brings me to have a look at the JFXPanel. The JFXPanel is a javax.swing.JComponent to embed JavaFX content into Swing-UIs. A JFXPanel can be used similar to a JPanel and can be accessed via the EDT as a generic Swing component except dealing with JavaFX component must be done via the JavaFX application thread.

To play around with that stuff I created two similar Panels (Swing + JavaFX) each with a Button, a TextField and a Label and placed them in a JSplitPane and a JFrame:

A closer look inside

To try Swing <-> JavaFX interoperability the buttons actions are setting the text from TextField to JLabel and vice versa.
There is nothing special with the JPanel as its handles generic Swing stuff, but with the JFXPanel containing the JavaFX controls:

public class SwingFXPanel extends JFXPanel {

    private Button testButton;
    private TextField testTextField;
    private Label testLabel;
    private VBox pane;

    public SwingFXPanel() {
        init();
    }

    private void init() {
        testButton = new Button("I am a JavaFX Button");
        testTextField = new TextField();
        testLabel = new Label("empty");
        pane = new VBox();
        pane.setAlignment(Pos.CENTER);
        pane.getChildren().addAll(testTextField, testButton, testLabel);
        Platform.runLater(this::createScene);
    }

    private void createScene() {
        Scene scene = new Scene(pane);
        setScene(scene);
    }

    public Button getTestButton() {
        return testButton;
    }

    public TextField getTestTextField() {
        return testTextField;
    }

    public Label getTestLabel() {
        return testLabel;
    }
}

Important here: to add the Scene to the JFXPanel within the JavaFX Application Thread:

Platform.runLater(this::createScene);

If you call:

createScene()

from another thread you get a Runtime-Exception:

java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0

Also each interaction with JavaFX related stuff must be placed on the JavaFX Application Thread:

E.g.:

Platform.runLater(() -> {
   swingFXPanel.getTestLabel().setText(swingPanel.getTestTextField().getText());
});
public class InteropFrame extends JFrame {

    private JSplitPane centralSplitPane;
    private SwingPanel swingPanel;
    private SwingFXPanel swingFXPanel;

    public InteropFrame(){
        init();
    }

    private void init() {
        setTitle("Swing <-> JavaFX Interoperatbiliy");
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        centralSplitPane = new JSplitPane();
        centralSplitPane.setDividerLocation(0.5);
        centralSplitPane.setResizeWeight(0.3);
        
        swingPanel = new SwingPanel();
        swingFXPanel = new SwingFXPanel();

        swingPanel.getTestButton().addActionListener((ActionEvent e) -> {
            Platform.runLater(() -> {
                swingFXPanel.getTestLabel().setText(swingPanel.getTestTextField().getText());
            });
        });


        swingFXPanel.getTestButton().setOnAction((javafx.event.ActionEvent t) -> {
            swingPanel.getTestLabel().setText(swingFXPanel.getTestTextField().getText());
        });

        centralSplitPane.setLeftComponent(swingPanel);
        centralSplitPane.setRightComponent(swingFXPanel);

        add(centralSplitPane, BorderLayout.CENTER);
    }
}

Alternatively also dealing with FXML is quite simple:

public class SwingFXMLPanel extends JFXPanel {

    @FXML
    private Button testButton;
    @FXML
    private TextField testTextField;
    @FXML
    private Label testLabel;

    private VBox rootPane;

    private URL fxmlResource;
    
    public SwingFXMLPanel(URL fxmlResource){
        this.fxmlResource = fxmlResource;
        init();
    }

    private void init(){
        rootPane = new VBox();
        FXMLLoader loader = new FXMLLoader(fxmlResource);
        loader.setController(this);
        loader.setRoot(rootPane);
        try {
            loader.load();
        } catch (IOException ex) {
            Logger.getLogger(SwingFXMLPanel.class.getName()).log(Level.SEVERE, null, ex);
        }

        testButton.setText("I am a JavaFX Button");
        testLabel.setText("empty");

        Platform.runLater(this::createScene);
    }

    private void createScene() {
        Scene scene = new Scene(rootPane);
        setScene(scene);
    }

    public Button getTestButton() {
        return testButton;
    }

    public TextField getTestTextField() {
        return testTextField;
    }

    public Label getTestLabel() {
        return testLabel;
    }

}

For me its very important to get the most possible acceptance of my co-workers to use JavaFX in Swing.

Therefore I want to simplify the specific FX application thread handling. So maybe this can be achieved if the major difference to using a JPanel is just to add:

private void createScene() {
        Scene scene = new Scene(rootPane);
        setScene(scene);
    }

and to call:

Platform.runLater(this::createScene);

inside the JFXPanel.

  • You can find the complete example code here.
Reference: Swing and JavaFX: working with JFXPanel from our JCG partner Jens Deters at the JavaFX Delight blog.
(0 rating, 0 votes)
You need to be a registered member to rate this.
1 Comment Views Tweet it!
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Paula Vieira Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
Paula Vieira
Guest
Paula Vieira

Thank you for this nice example. I have downloaded the complete example but I am having some problems reproducing your video. Basically, whenever I press the swing button, the content of the Swing Text Field appears in both Swing and JavaFX Labels, and whenever I press the JavaFx button, the content of the Swing Text Field also appears in both Swing and JavaFX Labels. Do you have any idea what is happening?

Thanks in advance.