Posterous theme by Cory Watilo

FX_AF

It seems now might be a good time for work to begin on a JavaFX Application Framework similar to what Swing Application Framework (now BSAF) achieved for Swing.

Leaving larger modular framework to Netbeans Platform - this would be a simple framework for JavaFX apps that provided the following:

  • Boilerplate/Harness Code in the form of a simple jar library
  • Best Practice approaches for Resource Management, i18n L10n etc..
  • Best practice for Testing (FEST etc)
  • Example/BluePrint applications
  • etc....

NetBeans Platform with JavaFX

So Aljoscha Rittner followed up on my initial posting and took it a step in the NetBeans Platform edition covered in his post here:

http://www.aljoscha-rittner.de/blog/archive/2011/03/04/javafxdev-netbeans-platform-with-javafx-2-0ea/

One insight from his post which was verified by Jonathan is the usage of Platform.runlater()

 Platform.runLater(new Runnable(){ 

It also looks like a rotated WebView will be the Hello World of JavaFX applications - much to Dean Riversons annoyance ;-)

 

Java FX2.0 - Embedding WebView in Swing

This is hopefully the start of a series of blog entries looking at JavaFX - specifically at Swing and JavaFX integration/interoperability.

I will be keeping things lean and letting the code speak for itself where possible.

In this first blog post I will set a simple foundation for following posts by quickly introducing two new greatly requested features
of JavaFX:

  • Embedding a Scene in a Swing application
  • HTML Rendering (Powered by WebKit)

But first an important health warning:
The content here is based on the early access release through the Oracle partner program. APIs and best practice may change significantly between now and the final version. I will endeavour reflect any changes back on these blogs.

The following example will show how to use the new Swing embedding features to add a WebView Node to a Scene and in turn add that Scene to a Swing application - my own version of JWebPane!

  
 
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javafx.collections.Sequence;
import javafx.embed.swing.JFXPanel;
 import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

import javax.swing.JButton;
 import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.sun.javafx.application.PlatformImpl;

/**
 * SwingFXWebView
 */
public class SwingFXWebView extends JPanel {
   
    private Stage stage;
    private WebView browser;
    private JFXPanel jfxPanel;
    private JButton swingButton;
    private WebEngine webEngine;

    public SwingFXWebView(){
        initComponents();
    }

    public static void main(String ...args){
   
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JFrame frame = new JFrame();
               
                frame.getContentPane().add(new SwingFXWebView());
               
                frame.setMinimumSize(new Dimension(640, 480));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });   
    }
   
    private void initComponents(){
       
        jfxPanel = new JFXPanel();
        createScene();
       
        setLayout(new BorderLayout());
        add(jfxPanel, BorderLayout.CENTER);
       
        swingButton = new JButton();
        swingButton.addActionListener(new ActionListener() {
           
            @Override
            public void actionPerformed(ActionEvent e) {
                webEngine.reload();
            }
        });
        swingButton.setText("Reload");
       
        add(swingButton, BorderLayout.SOUTH);
    }   
   
    /**
     * createScene
     *
     * Note: Key is that Scene needs to be created and run on "FX user thread"
     *       NOT on the AWT-EventQueue Thread
     *
     */
    private void createScene() {
        PlatformImpl.startup(new Runnable() {
            public void run() {
               
                stage = new Stage();
               
                stage.setTitle("Hello Java FX");
                stage.setResizable(false);
 
                Group root = new Group();
                Scene scene = new Scene(root,80,20);
                stage.setScene(scene);
               
               
                URL url = null;
                try{
                    url = new URL("http://www.google.ie");
                }catch(Exception ex){
                    ex.printStackTrace();
                }
                webEngine = new WebEngine(url);
                browser = new WebView(webEngine);

                Sequence<Node> children = root.getChildren();
                children.add(browser);                   
               
                jfxPanel.setScene(scene);
            }
        });
    }   
}


As you can see if you are familiar to Swing the code is self explanatory. The main moving parts involved are simply:

  • New javafx.embed.swing.* package
    • Specifically JFXPanel
  • Ensuring the JavaFX elements are created on the special FX Thread
  • The Browser elements (WebView node and WebEngine)

The following is a simple screenshot of the above code showing the WebView FX Node and Swing JButton beneath.

Swingfxwebview

It will be interesting to hear peoples feedback on these two much requested features.

It's unclear right now what the logistics of packaging a hybrid application like this will be as there are platform specific components (the native WebKit parts etc) involved. So I won't be able to answer any questions relating to that or anything to do with how this behaves on other platforms until newer releases of the JavaFX toolkit.

That is all for now....