Tag Archives: jnlp

JavaFX to JavaScript and Back Part 2

Tons of Bouncy Balls

Tons of Bouncy Balls

Introduction

In the second installment of the series “JavaFX to JavaScript and Back” we will look at code! If you remember what we discussed in my previous post of Part 1 showing a demo of many bouncy balls. If you want to skip to the source code go to demo and click on download project.

Newcomers

If you are new and just getting started with JavaFX I strongly suggest JavaFX.com or Java.sun.com. If you are like me, one who knows enough to be dangerous please skip to Getting Started. Newcomers should take a look at books in the References section at the end of this article. Another awesome resource is the “Free” 15-Week JavaFX Programming (with Passion!) Online Course w/ Sang Shin & James Weaver.

Assumptions

  • NetBeans 6.5.1 is installed with JavaFX 1.2 pluggin.
  • Java SDK 1.6 update 14
  • Know basic JavaScript
  • Know basic HTML

Getting started

To give you a quick recap of the scenarios:

  1. Create Bouncy Balls (JavaScript to JavaFX)
  2. Remove Bouncy Balls (JavaFX to JavaScript)

Create a JavaFX Applet

Step 1: Create a Ball (Custom Node)
First create a class called Ball that extends a CustomNode. The key is overriding the create() method of the CustomNode class. We first create a Circle with a RadialGradient fill. Next we create a Group containing the circle in its content attribute. Then add the onMousePressed function to the group to detect a mouse pressed event which will remove this ball’s instance from the Scene (Game Area) and decrements the numBalls variable which updates the Web Page’s form element Number of Balls. Finally we return the group (ball variable).

class Ball extends CustomNode {
    public var velocity:Velocity;
    public var centerX:Integer=100;
    public var centerY:Integer=100;
    public var radius:Integer;
    public var fill:Color;
    protected override function create(): Node {
        var circle:Circle = Circle {
                centerX: centerX, centerY: centerY
                radius: radius
                fill: RadialGradient {
                        centerX: centerX - radius / 3
                        centerY: centerY - radius / 3

                        radius: radius
                        proportional: false
                        stops: [
                            Stop {
                                offset: 0.0
                                color: getRndColor()
                            },
                            Stop {
                                offset: 1.0
                                color: Color.BLACK
                            }
                        ] // stops
                } // RadialGradient
        } // circle
        var ball = Group{
            content:[circle];
            // remove ball
            onMousePressed: function( e: MouseEvent ):Void {
                delete this from gameArea;
                numBalls--;
            }
        } // Group

        return ball;
    } // create()
} // Ball

Step 2: Create initial ball to be put in Scene

You should notice I’ve created a few script level functions which conveniently return random values to create a Ball node. I won’t list those function for brevity. The random generated attributes are: velocity, centerX, centerY, radius, circle.fill = (RadialGradient 1st stop Color [Step 1 – Line 19])

// create an initial ball to float around.
var initialBallRadius = getRndRadius();
var rndCenter:Point = getRndCenter(500, 400, initialBallRadius);
var firstBall = Ball{
    velocity:getRndVelocity()
    centerX: rndCenter.x
    centerY: rndCenter.y
    radius: initialBallRadius
};

Step 3: Create the Scene to display Balls
The variable gameArea is a sequence of Nodes. You will notice the ball instance from Step 2 is the first node in the sequence. The scene’s content attribute is bound to the gameArea variable. During run time as nodes are added and removed from the game area the scene will dynamically update the visible nodes.

var gameArea:Node[] = [firstBall, toggleAnimationButton, mainRectRegion];
var scene:Scene = Scene {
        content: bind gameArea
        fill:Color.TRANSPARENT
};

Step 4: Create the Stage
This is the top level container which holds the scene.

Stage {
    title: "Application title"
    width: 500
    height: 400
    opacity: bind mainScreenOpacity;
    scene: scene
}

Step 5: Create a game or animation loop using the Timeline class
Here we create a Timeline instance that will run indefinitely (Timeline.INDEFINITE) with a single key frame (KeyFrame) which periodically updates each bouncy ball’s attributes which eventually renders each ball node with a new x and y position based on the velocity. Also the Timeline (gameLoop) is started immediately using the play() function.

var gameLoop:Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames : [
        KeyFrame {
            time: 1s / 50
            canSkip : true
            action: function() {
                for (node:Node in gameArea) {
                    if (not (node instanceof Ball)){
                        continue; // don't update non balls
                    }
                    var ball = node as Ball;
                    var xMin = ball.boundsInParent.minX;
                    var yMin = ball.boundsInParent.minY;
                    var xMax = ball.boundsInParent.maxX;
                    var yMax = ball.boundsInParent.maxY;

                    // Collision - boundaries
                    if (xMin  scene.width){
                       ball.velocity.xVelocity = ball.velocity.xVelocity * -1;
                    }
                    if (yMin  scene.height){
                       ball.velocity.yVelocity = ball.velocity.yVelocity * -1;
                    }

                    ball.translateX = ball.translateX + ball.velocity.xVelocity;
                    ball.translateY = ball.translateY + ball.velocity.yVelocity;
                }
            } // action
        } //
    ]
};
gameLoop.play();

Step 6: Create the AppletStageExtension
This is the reference to the JavaFX applet which would assist with browser functionality such as the evaluation of JavaScript code.

var applet: AppletStageExtension;

Step 7: Create the numBalls variable keeping track of adds and removes.
The numBalls variable has a trigger (on replace) that updates the HTML page’s input text field “numBalls“. You should notice the id attribute of the tag is name “numBalls“. An id is a way to uniquely locate the form element in the HTML DOM (in this case a reference to the input field. When numBalls variable changes the trigger will evaluate the JavaScript code “document.getElementById(‘numBalls’).value = {numBalls}”. What this does is populate the form element field’s ‘id’ called “numBalls” whenever the JavaFX variable numBalls is updated.

var numBalls:Integer = 1 on replace {
    applet.eval("document.getElementById('numBalls').value = {numBalls}");
};

Step 8: Create a JavaFX function to add lots of balls

The HTML Web page will have a JavaScript function that would call the JavaFX function below when the user presses the Add Ball(s) button.  javafxtojavascriptandback8You will notice the FX.deferAction() call, which ensures updates to JavaFX classes are happening on the JavaFX main processing thread. This function will instantiate num balls inserts into the game area (Scene content) and increments the numBalls (trigger will update Web page’s form element).

// This function is called from the JavaScript button and numBallsToAdd field
function addBalls(num:Integer) : Void {
    FX.deferAction(function() : Void {
        for( i in [1..num]){
            var curBallRadius = getRndRadius();
            var rndCenter:Point = getRndCenter(500, 400, curBallRadius);
            var b = Ball{
                velocity:getRndVelocity()
                centerX: rndCenter.x
                centerY: rndCenter.y
                radius: curBallRadius
                fill: getRndColor()
            };
            insert b into gameArea;
            numBalls++;
        }
    });
}

Create a HTML Web page containing the JavaFX applet

Step 9: Create HTML Web page to display JavaFX applet

Run in Browser

Run in Browser

After creating the project in NetBeans select project / properties / Run (categories) / Application Execution Model – Run in Browser.

Step 10: Build Project

Building the project which will create files in the {PROJECT_HOME}/dist directory.

Step 11: Copy originally NetBeans created HTML file of the dist directory to another name

Use the copied and renamed HTML file and not the original because when the build process occurs it will overwrite the original HTML generated file.

Step 12: Modify HTML code to contain JavaScript to call JavaFX applet.

    javafx(
        {
              archive: "JavaFXtoJavaScript.jar",
              draggable: true,
              width: 500,
              height: 400,
              code: "javafxtojavascript.Main",
              name: "JavaFXtoJavaScript",
			  id: "ballApp"
        },
		{ isApplet: "true" }
    );

function addBalls() {
	document.ballApp.script.addBalls(document.getElementById('numBallsToAdd').value);
}

Step 13: Modify HTML to contain Form Elements.

<form>
<table>
<tr><th>Add balls to Scene :</th>
<td><input id=”numBallsToAdd” name=”numBallsToAdd” value=”1″/></td>
<td><input onClick=”addBalls();” type=”button” name=”addButton” value=”Add Ball(s)”/></td>
</tr>
<tr>
<th>Number of balls: </th>
<td><input id=”numBalls” name=”numBalls” READONLY/></td>
</tr>
</table>
<br/>
</form>

Running Applet in Browser through NetBeans

Step 14: Run application or hit F6 key

This will launch the JavaFX applet into the browser from the original HTML page created from the build. Go to the address and modify the URL (Just the file name) to use the modified copy which would run the JavaFX applet along with the form elements added from step 12 – 13.

Conclusion

Although the example only used simple attributes of the AppletStageExtension there are other properties and events to explore such as onAppletRestored, showDocument(), etc.  Hopefully we can get away from HTML and just have rich client applications, however I don’t think the browser is going away anytime soon. So we can happily go from JavaFX to JavaScript and Back!

Enjoy. Let me know what you think.

References:

Pro JavaFX Platform by Jim Weaver, Weiqi Gao, Stephen Chin, and Dean Iverson
JavaFX: Developing Rich Internet Applications by Jim Clarke, Jim Connors and Eric J. Bruno
Essential JavaFX by Gail Anderson and Paul Anderson

numBalls

JavaFX to JavaScript and Back Part 1

Introduction

One of the most impressive features that I’ve seen relating to JavaFX, is the ability of an Applet to interact with the browser via JavaScript and HTML. The browser can also interact back with JavaFX code. There are plenty of examples out there but I’d like to add one more to the pile of cool examples. It may be cool using AJAX concepts with JavaScript & HTML, but using the concept with JavaFX is just amazing. The possibilities are endless. “JavaFX to JavaScript and Back Part 1” will demonstrate what the application will do and “JavaFX to JavaScript and Back Part 2” will be on steps on how-to do it.

While I was a kid growing up, I would go to the bowling alley to get a 25 cent(US) bouncy ball from the vending machine. I’ve lost many a bouncy ball in the parking lot from bouncing them as hard as I could. In this example I will create a 500 by 400 pixel sized bouncy ball containment field in JavaFX. This is to prevent them from ever leaving me like they did when I was a kid. 😦

Note: Thanks to Stephen Chin an author of the book Pro JavaFX Platform and WidgetFX for allowing me to host The Bouncy Ball Containment Field Click Here to run!

(Tip: If in Firefox just middle mouse click link to launch in another tab)

Initial Ball added to ball world

Here is an example of an HTML page with an embedded JavaFX applet with HTML form elements below for data input to create bouncy balls. The demo allows a user to specify the number of balls to add to the scene called the “Add balls to Scene” field.  When the “Add Ball(s)” button is pressed the JavaScript code will pass the number of balls to the JavaFX public script level function called addBalls() which will create bouncy balls. When balls are added the JavaFX Script code will talk back to the HTML read-only field called “Number of balls” to show the current number of balls in the containment field (Scene). On the JavaFX side of things the location, velocity, size and color of the balls will be generated randomly and rendered on the scene.  You should notice the new JavaFX 1.2 Toggle Button component on the upper left. It is used to stop and  start the animation of the bouncing of the balls (Timeline pause & play to be exact). The first use case scenario is add balls which depicts the JavaScript to JavaFX data flow. The second use case scenario is display the current number of bouncy balls in the containment field which depicts the JavaFX to JavaScript data flow.

Balls addBalls(lots of balls)

This shows when the user specifies a whole bunch of balls to add.

Button to use JavaScript function addBalls()
Button to use JavaScript function addBalls()

A ball can be removed from the scene by just clicking an individual ball.  The field “Number of balls” input field is really a read-only field that is updated from the JavaFX side whenever balls are added and removed from the bouncy ball containment field.

More Bouncy Balls

By adding many balls I wanted to see how well it would perform.

Tons of Bouncy Balls

Here I add balls, lots of balls! The bouncy ball containment field now holds 400 bouncy balls. Although I might not be doing things efficiently I noticed my CPU was performing adequately. The utilization was between 41% to 46% (older Dell hyper-threading Inspiron XPS laptop Pentium(R) 4 CPU 3.40 GHz) using Windows XP SP 3. It was a smooth animation with no flicker. The Ball class is a Custom Node which contains a Circle with an effect called Radial Gradient to give it a 3D sphere look.

Dragging JavaFX Applet out of Web Page

By using the Alt key along with mouse drag the JavaFX applet will appear to be pulled out of the browser’s Web page and out onto the desktop.

JavaFX Applet living outside of browser

By default, when you drag the applet out of the browser onto your desktop a small “close button” appears on the upper right corner of your application. When the user clicks the “close button” box the JavaFX applet will snap right back into the browser. Another thing to note is that when the JavaFX applet is running outside the browser and the user subsequently closes the browser the applet will remain running independent of the browser.   This introduces an interesting ability that adds a new dimension to usability on the desktop.  As the user becomes drawn into the application experience the need to be attached to the Web page will be obsolete. Another cool effect that I have added to the Application is transparency or opacity level when the mouse cursor is exiting or entering the scene area. When the user moves the mouse away from the application the screen will fade to a subtle transparency. When the user moves the mouse cursor into the application screen area the background becomes fully opaque (white in this case).

Fully Opaque when mouse moves into application

Fully Opaque when mouse moves into application

This fading effect helps the user transition from one application to another.

The last, item of the desktop experience to mention is the Java JNLP mechanism that asks the user if he or she wants to create a short-cut icon for the application to launch at a later time.

Create short-cut dialog

Create short-cut dialog

To reproduce the dialog asking for a shortcut, you would drag the applet out of browser, then close tab or browser application and then a dialog will appear asking to create the short-cut.

Conclusion

Building the bouncy ball containment field was extremely fun. I learned a lot about boundsInParent which taught me that it is the rectangular region after all transformations to the node has been applied when adding balls to the Scene. As the future of the Web 2.0 apps grow users will demand richer interfaces and better content. I believe JavaFX has made great strides in desktop development and also increasing the usability factor of desktop applications by leaps and bounds. In Part 2 of “JavaFX to JavaScript and Back” I will detail a step-by-step tutorial on how to build the JavaFX applet you see here. Let me know what you think. Feedback is always welcome!