Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Integrate JavaFX into the NetBeans Platform Menubar

DZone's Guide to

How to Integrate JavaFX into the NetBeans Platform Menubar

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

Let's say you want to replace the NetBeans Platform menubar, written in Swing, with one written in JavaFX. Why? For fun. Also, CSS stylesheet support in JavaFX is handy for redesigning the menubar's appearance: 

The coloring in the menubar above, which is indeed a JavaFX MenuBar, is as follows:

/*Menu Bar*/
.menu-bar {
    -fx-background-color: orange;
}

/*Menus*/
.menu .label {
    -fx-text-fill: black;
}

/*Menu Items*/
.menu-item:focused {
    -fx-background-color: greenyellow;
}
.menu-item .label {
    -fx-text-fill: black;
}

Here's some references relevant to this task:

And here's the steps, all based on the links above:

  1. Remove the default menubar and replace with your own:
    package org.demo.menu;
    
    import org.openide.modules.OnStart;
    
    @OnStart
    public class Installer implements Runnable {
    
        @Override
        public void run() {
            System.setProperty("netbeans.winsys.menu_bar.path", "LookAndFeel/MenuBar.instance");
        }
    
    }
  2. In the layer, i.e., as referred to in the folder location above, define your Swing menubar:
    <folder name="LookAndFeel">
        <file name="MenuBar.instance">
            <attr name="instanceOf" stringvalue="org.openide.awt.MenuBar"/>
            <attr name="instanceCreate" newvalue="org.demo.menu.MyMenuBar"/>
        </file>
    </folder>
  3. Now create the class that you defined above. Start by putting a JFXPanel into the Swing menubar. Then you're good to go. Just add the MenuBar, Menus, and MenuItems from JavaFX, based on what you find in the relevant folders in the application's filesystem.
    public class MyMenuBar extends JMenuBar {
    
        public MyMenuBar() {
            final JFXPanel menuFxPanel = new JFXPanel();
            add(menuFxPanel);
            Platform.setImplicitExit(false);
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    Scene scene = new Scene(new VBox(), 400, 20);
                    scene.getStylesheets().add(MyMenuBar.class.
                            getResource("myMenuBar.css").toExternalForm());
                    MenuBar menuBar = new MenuBar();
                    FileObject menuFolder = FileUtil.getConfigFile("Menu");
                    FileObject[] menuKids = menuFolder.getChildren();
                    for (FileObject menuKid : FileUtil.getOrder(Arrays.asList(menuKids), true)) {
                        Menu newMenuFromFileObject = new Menu(menuKid.getName());
                        menuBar.getMenus().add(newMenuFromFileObject);
                        builtMenuStructure(menuKid, newMenuFromFileObject);
                    }
                    ((VBox) scene.getRoot()).getChildren().addAll(menuBar);
                    menuFxPanel.setScene(scene);
                }
            });
        }
    
        private void builtMenuStructure(FileObject fo, Menu menu) {
            DataFolder df = DataFolder.findFolder(fo);
            DataObject[] childs = df.getChildren();
            for (DataObject oneChild : childs) {
                if (oneChild.getPrimaryFile().isFolder()) {
                    FileObject childFo = oneChild.getPrimaryFile();
                    Menu newMenu = new Menu(childFo.getName());
                    menu.getItems().add(newMenu);
                    builtMenuStructure(childFo, newMenu);
                } else {
                    Object instanceObj = FileUtil.getConfigObject(
                      oneChild.getPrimaryFile().getPath(), 
                      Object.class);
                    if (instanceObj instanceof JSeparator) {
                        menu.getItems().add(new SeparatorMenuItem());
                    } else if (instanceObj instanceof Action) {
                        final Action a = (Action) instanceObj;
                        String name = (String) a.getValue(Action.NAME);
                        String cutAmpersand = Actions.cutAmpersand(name);
                        MenuItem menuItem = new MenuItem(cutAmpersand);
                        menuItem.setOnAction(new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(final ActionEvent t) {
                                try {
                                    SwingUtilities.invokeAndWait(new Runnable() {
                                        @Override
                                        public void run() {
                                            java.awt.event.ActionEvent event =
                                                    new java.awt.event.ActionEvent(
                                                    t.getSource(),
                                                    t.hashCode(),
                                                    t.toString());
                                            a.actionPerformed(event);
                                        }
                                    });
                                } catch (InterruptedException ex) {
                                    Exceptions.printStackTrace(ex);
                                } catch (InvocationTargetException ex) {
                                    Exceptions.printStackTrace(ex);
                                }
                            }
                        });
                        menu.getItems().add(menuItem);
                    }
                }
            }
        }
    
    }

That's all and you're done. Congratulations, you've replaced the default Swing menubar in the NetBeans Platform with a new one defined in JavaFX.

Maybe handy to know what the import statement in the above class are:

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.layout.VBox;
import javax.swing.Action;
import javax.swing.JMenuBar;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import org.openide.awt.Actions;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.util.Exceptions;

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}