DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • DGS GraphQL and Spring Boot
  • Auto-Instrumentation in Azure Application Insights With AKS
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Why Mocking Sucks

Trending

  • DGS GraphQL and Spring Boot
  • Data Quality: A Novel Perspective for 2025
  • Metrics at a Glance for Production Clusters
  • Integrating Model Context Protocol (MCP) With Microsoft Copilot Studio AI Agents
  1. DZone
  2. Coding
  3. Java
  4. How to Integrate JavaFX into a NetBeans Platform Wizard (Part 1)

How to Integrate JavaFX into a NetBeans Platform Wizard (Part 1)

By 
Sean Phillips user avatar
Sean Phillips
·
Apr. 26, 13 · Interview
Likes (0)
Comment
Save
Tweet
Share
22.4K Views

Join the DZone community and get the full member experience.

Join For Free

When working within the NetBeans Platform, Swing is King. JavaFX is the crown prince. However, some developers avoid developing GUI controls with JavaFX in the NetBeans Platform because Swing is available by default. Well, it is possible to develop your JavaFX forms and simply replace the default NetBeans panels. The following tutorial explains how a developer can take a JavaFX GUI form and FXML developed using Scene Builder and replace a NetBeans Platform Wizard visual panel with minimal effort. 

Now, why would this concept be useful? Well, consider a development team where new Java applications are being written in JavaFX.  Why rewrite the useful Panel classes to Swing just to use them within a NetBeans Platform Wizard? Why force new form development to be in Swing just to be compatible with a NetBeans Platform application?  NetBeans Platform applications are perfectly capable of rendering JavaFX interop'd with Swing. Here's how:


First you will need to do a little prep work to setup an application for this tutorial. Do the following:

  1. Create the JavaFX GUI. Create a new JavaFX FXML GUI using SceneBuilder. Add the controls you want and generate your FXML file and controller class.

  2. Update your Controller Class by Extending JFXPanel. This is part of the Swing Interop pattern that we all know and love. You will also need to @Override the getName() method so that the wizard framework can update the current step title.

  3. Encapsulate fields/values. Create public methods that will provide Wizard framework with the fields it needs to pass from panel to panel. This is the same thing you would need to do with a standard Swing Wizard JPanel class.

    The code for your controller class still runs without a problem within your JavaFX application but is now Swing Interop compatible. The code might look like this:

    package jfxwizpanel.jfxwiz;
    
    import java.io.File;
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.embed.swing.JFXPanel;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.TextField;
    import javafx.stage.FileChooser;
    
    /**
     *
     * @author SPhillips (King of Australia)
     */
    public class WizPanelController extends JFXPanel implements Initializable {
        @FXML //  fx:id="browseButton"
        private Button browseButton; // Value injected by FXMLLoader
        @FXML //  fx:id="pathText"
        private TextField pathText; //Field that Path is stored in
        private String filePath = ""; //some value to pass to the next Wizard panel
        
        // Handler for Button[fx:id="browseButton"] onAction
        public void handleButtonAction(ActionEvent event) {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("Select File");
            //Show open file dialog
            File file = fileChooser.showOpenDialog(null);
            if(file!=null) {
                setFilePath(file.getPath());
                pathText.setText(filePath);
            }
        }
        @Override // This method is called by the FXMLLoader when initialization is complete
        public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
            assert browseButton != null : "fx:id=\"browseButton\" was not injected: check your FXML file 'WizPanel.fxml'.";
            assert pathText != null : "fx:id=\"pathText\" was not injected: check your FXML file 'WizPanel.fxml'.";
            // initialize your logic here: all @FXML variables will have been injected
        }
        @Override //This method is used by Wizard Framework to generate list of steps
        public String getName() {
            return "FXML JFXPanel";
        }    
        /**
         * @return the filePath
         */
        public String getFilePath() {
            return filePath;
        }
        /**
         * @param filePath the filePath to set
         */
        public void setFilePath(String filePath) {
            this.filePath = filePath;
        }
    }
    And when you run this Code within the JavaFX FXML application you get something like the following screenshot:



  4. Create the NetBeans Platform Application. Create a new NetBeans Platform application and add a new module. Add a Wizard using the "Wizard" Wizard.

  5. Include the JavaFX Runtime. Create a NetBeans library wrapper module to include "jfxrt.jar" and set a dependency on it in the module described above.

  6. Copy Controller class and FXML file. As of NetBeans 7.3 you cannot refactor copy these files from your JavaFX FXML project to your NetBeans Platform application package. After manually copying these two files you will need to do a manual replace of the package path in both the Controller class and the fx:controller string in the FXML file.

    Your FXML code might now look something like this:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.geometry.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.web.*?>
    
    <AnchorPane id="AnchorPane" prefHeight="410.0" prefWidth="582.0" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxwizard.jfxwiz.WizPanelController">
      <children>
        <VBox id="VBox" prefHeight="410.0000999999975" prefWidth="582.0" spacing="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
          <children>
            <AnchorPane id="AnchorPane">
              <children>
                <RadioButton layoutX="161.0" layoutY="14.0" mnemonicParsing="false" prefWidth="134.0" text="Prefer Swing" />
                <RadioButton layoutX="14.0" layoutY="14.0" mnemonicParsing="false" prefWidth="134.0" selected="true" text="Prefer JavaFX" />
              </children>
            </AnchorPane>
            <AnchorPane prefHeight="45.0" prefWidth="310.0">
              <children>
                <Button fx:id="browseButton" layoutX="486.0" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="45.0" prefWidth="72.0" text="Browse" />
                <TextField fx:id="pathText" layoutX="14.0" layoutY="4.0" prefHeight="41.0" prefWidth="461.0" />
              </children>
            </AnchorPane>
            <AnchorPane prefHeight="272.0" prefWidth="572.0">
              <children>
                <HTMLEditor prefHeight="272.0" prefWidth="572.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
              </children>
            </AnchorPane>
          </children>
          <padding>
            <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
          </padding>
        </VBox>
      </children>
    </AnchorPane>
  7. Replace Swing Panel with FXML Controller. At this point you can replace the autogenerated Swing JPanel class that would normally be loaded by the Wizard control class with your JavaFX FXML controller. Remember we extended JFXPanel and it pays off here. All we have to do now is follow our standard Swing Interop technique. However this time we have to use our Platform.runLater() pattern in the getComponent() method of the Wizard controller class.

    Below is the relevant code after the update. Notice how little we had to change:

    public class JfxwizWizardPanel1 implements WizardDescriptor.Panel<WizardDescriptor> {
    
        /**
         * The visual component that displays this panel. If you need to access the
         * component from this class, just use getComponent().
         */
        //private JfxwizVisualPanel1 component;
        public WizPanelController component; //Replaces original autogenerated JPanel class 
    
        // Get the visual component for the panel. In this template, the component
        // is kept separate. This can be more efficient: if the wizard is created
        // but never displayed, or not all panels are displayed, it is better to
        // create only those which really need to be visible.
        @Override
        public WizPanelController getComponent() {
            if (component == null) {
                component = new WizPanelController(); //return new JFXPanel controller
                Platform.setImplicitExit(false);
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        createScene();  //standard Swing Interop Pattern
                    }
                });
            }
            return component;
        }
    
        private void createScene() {
            try {
                URL location = getClass().getResource("WizPanel.fxml"); //same FXML copied from JavaFX app
                FXMLLoader fxmlLoader = new FXMLLoader();
                fxmlLoader.setLocation(location);
                fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
                Parent root = (Parent) fxmlLoader.load(location.openStream());
                Scene scene = new Scene(root);
                component.setScene(scene);    
                component = (WizPanelController) fxmlLoader.getController();    
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }

    At this point, you should be able to resolve any import issues, compile and run. You should see your JavaFX GUI nicely loaded within the Wizard Dialog frame like the screenshot below:


Wow that's awesome that you can load JavaFX GUIs into your wizards.  But you didn't do anything with the information, so you didn't actually leverage the WizardDescriptor framework. 


JavaFX NetBeans application

Opinions expressed by DZone contributors are their own.

Related

  • DGS GraphQL and Spring Boot
  • Auto-Instrumentation in Azure Application Insights With AKS
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Why Mocking Sucks

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!