Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

Geertjan is a DZone Zone Leader and has posted 421 posts at DZone. You can read more from them at their website. View Full User Profile

JavaFX 2.0 in NetBeans RCP

05.09.2011
Email
Views: 7034
  • submit to reddit

Below follows a prototype of the current state of JavaFX integration into NetBeans RCP. It is a prototype only and does not reflect in any way the final state of this integration. (Hopefully, in fact, it will all end up being a lot simpler and more intuitive than what is described below.)

One of the samples that comes with the JavaFX 2.0 distro is this brick game:

Fortunately, it comes as a NetBeans project:

As you can see, above, the application's Main class extends the "javafx.application.Application" class, which starts the JavaFX lifecycle, together with its own special JavaFX thread.

Now, let's move the brick game to NetBeans RCP. One of the many apps on NetBeans RCP is NetBeans IDE. So, as an example, we're going to learn how to play the JavaFX brick game within NetBeans IDE:

Take the following steps:

  1. Read background documents. Read this NetBeans FAQ by Tom Wheeler and this blog entry by Josch Rittner.

  2. Become a JavaFX partner. So that you can get hold of early JavaFX distros.

  3. Create a JavaFX main class for your NetBeans RCP project. Start by creating a Java library project in NetBeans IDE, add the "jfxrt.jar" from the JafaFX distro as a library, and create this class, which you understand because you've done step 1 of these instructions:
    package mymain;

    import java.lang.reflect.Method;
    import javafx.application.Application;
    import javafx.stage.Stage;

    public class CustomStartup extends Application {

    private static final String NB_MAIN_CLASS = "org.netbeans.core.startup.Main";

    public static void main(String[] args) throws Exception {
    // do whatever you need here (e.g. show a custom login form)
    System.out.println("Launch Java FX");
    long ms = System.currentTimeMillis();
    // create JavaFX scene
    Application.launch(CustomStartup.class, args); // This is the main start up for JavaFX 2.0
    System.out.println("Launched Java FX in " + (System.currentTimeMillis() - ms) + "ms");
    // once you're done with that, hand control back to NetBeans
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    Class mainClass = Class.forName(NB_MAIN_CLASS, true, classloader);
    Object mainObject = mainClass.newInstance();
    Method mainMethod = mainClass.getDeclaredMethod("main", new Class[]{String[].class});
    mainMethod.invoke(mainObject, (Object) args);
    }

    @Override
    public void start(Stage stage) {
    // Nothing to do, forget the stage....
    }

    }

    This is what the Java library project should now look like:

  4. Put the JAR in the boot classpath. Take the JAR that you create from the above Java library project and put it in your application's "platform/core" folder, with the "jfxrt.jar" in the "platform/lib" folder, and all the DLL's in a new "bin" folder:


  5. Port the brick game to a NetBeans module. Create a new module, wrap the "jfxrt.jar" into the module, copy all the classes from the brick game into the module, create a new window, judiciously copy the code from the "Main.java" class into the new window, making use of a JFXPanel, as follows:
    Platform.runLater(new Runnable() {
    @Override
    public void run() {
    Config.initialize();
    Group root = new Group();
    mainFrame = new MainFrame(root);
    Scene scene = new Scene(root);
    scene.setFill(Color.BLACK);
    jFXPanel1.setScene(scene);
    mainFrame.changeState(MainFrame.SPLASH);
    }
    });

    The good news is, once you have a JavaFX scene, you can use "JFXPanel.setScene" and add the JFXPanel to the TopComponent. Then you're done, you've integrated your Scene into Swing, i.e., JavaFX is now running in Swing.

  6. Specify your JavaFX main class. Open the "project.properties" of the module and add this line:
    run.args.extra=-J-Dnetbeans.mainclass=mymain.CustomStartup

    Now run the module. The application (in this case, NetBeans IDE) starts up, the "MyMain.jar" is in the boot classpath, the main class is specified in the module, so JavaFX is started up, then the window opens, and your game begins.

The only real question to ask is "Why". In corporate applications (i.e., the kinds of application requirements that result in NetBeans RCP being used), games are not very useful. Charts, on the other hand, are very usseful indeed and JavaFX comes with its own set of charts, which we'll look at another time.

One very cool thing would be if we had a "JavaFX Starter" module in the NetBeans Plugin Portal. When you'd install this module into any NetBeans RCP application, the "MyMain.jar" above would be put into "platform/core", the "jfxrt.jar" would be put into "platform/lib" and the DLL's would be put into "platform/bin". I.e., all these files would exist in the module and the module would put them into all the right places. The module would then cause a restart of the application, at which point the module's own "run.args.extra" would be used to use the new JavaFX main class shown above. Then anyone could install JFXPanels into their NetBeans RCP applications, without needing to think about the JavaFX startup requirements.

 

Published at DZone with permission of its author, Geertjan Wielenga.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Jesse Glick replied on Mon, 2011/05/09 - 3:57pm

On Ubuntu I was able to embed a JFXPanel in a simple Swing app (JFrame) without using Application at all:

public static void main(String[] args) throws Exception {
JFrame fr = new JFrame("Launched normally inside Swing");
fr.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JFXPanel panel = new JFXPanel();
fr.getContentPane().add(panel);
fr.getContentPane().add(new JLabel("This is just Swing here"), BorderLayout.PAGE_START);
fr.setSize(500, 500);
fr.setVisible(true);
com.sun.javafx.application.PlatformImpl.startup(new Runnable() {
public void run() {
final Scene scene = new Scene(new Group(), 600, 300);
scene.getStylesheets().add("/shelf/displayshelf.css");
Image[] images = new Image[IMAGE_NAMES.length];
for (int i = 0; i < images.length; i++) {
Image image = new Image(SwingMain.class.getResource("images/" + IMAGE_NAMES[i]).toExternalForm(), 200, 200, true, true, false);
images[i] = image;
}
scene.setRoot(new DisplayShelf(images));
panel.setScene(scene);
}
});
}

I tried to use the same trick in a TopComponent, but sometimes it gives me a SIGSEGV and sometimes shows nothing. Also the panel in the trivial Swing app sometimes gives a SIGSEGV too.

 If you do not use PlatformImpl.startup then you just get an IllegalStateException from PlatformImpl.runLater saying the toolkit is not initialized. Seems like something the FX team needs to fix.

Dominique De Vito replied on Tue, 2011/05/10 - 6:30am

JavaFX sounds like the new Swing...

Michael Mann replied on Wed, 2011/08/17 - 4:14pm

Hi Geertjan,   I implemented all of the suggestions as recommended from Tom Wheeler and yourself and actually was able to get my JavaFX chart to come up fine within a Netbean's TopComponent. However....(and here is the problem), when I close out the TopComponent, the internal "JavaFx Application Thread" will always terminate when closing a TopComponent. Upon trying to re-open the TopComponent, the JavaFX Application thread is no longer there for course, and in essence I get a stale bitmap image of the just before the prior close operation on the TopComponent. What was interesting as a side not, was that when I ran everything in the debugger, and I "suspend" the JavaFX Application thread PRIOR to closing out my TopComponent, the JavaFX thread will still be there. Then AFTER re-opening the TopComponent and "resuming" the JavaFX thread in the debugger - all behaves well. So... I was wondering if you or some of you friends might know a good work around to use when dealing with these TopComponent states mixed with JavaFX. The TRIMP Suite development is growing rapidly, and I want (need....lol) JavaFX for some animation purposes, etc. with our application. I have tested and wired up communication just fine between Java and JavaFX as described in the tutorials, and it looks like this "minor" threading issue is all that is keeping developers from running wild with JavaFX in Netbeans.   Thanks,   -Mike

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.