X

jjs -fx

Jim Laskey
Senior Development Manager
So after some playing around and working with the JavaFX folks, I think we have a proposal for jjs that works with JavaFX.  The -fx flag on jjs will bootstrap scripts using a javafx.application.Application.  Thus, writing JavaFX scripts in Nashorn is very easy.

The basic command line is;

jjs -fx fxscript.js
You can mix and match other jjs options like -scripting and -- ;

jjs -fx -scripting fxscript.js -- my script args
The content of the script follows some of the examples I've posted before.  The script may optionally contain JavaFX init, start and/or stop functions.  What is new, is that you can leave them behind and just straight script.  The original hello world example;

var Button    = Java.type("javafx.scene.control.Button");
var StackPane = Java.type("javafx.scene.layout.StackPane");
var Scene = Java.type("javafx.scene.Scene");
function start(stage) {
stage.title = "Hello World!";
var button = new Button();
button.text = "Say 'Hello World'";
button.onAction = function() print("Hello World!");
var root = new StackPane();
root.children.add(button);
stage.scene = new Scene(root, 300, 250);
stage.show();
}

becomes;

var Button    = Java.type("javafx.scene.control.Button");
var StackPane = Java.type("javafx.scene.layout.StackPane");
var Scene = Java.type("javafx.scene.Scene");
$STAGE.title = "Hello World!";
var button = new Button();
button.text = "Say 'Hello World'";
button.onAction = function() print("Hello World!");
var root = new StackPane();
root.children.add(button);
$STAGE.scene = new Scene(root, 300, 250);
$STAGE.show();

where the stage is now a global var $STAGE (instead of the start function argument.)

Also for convenience, we've predefined includes for all of the JavaFX classes.  I would recommend using only the classes you need (only needed for new and for static field access), but for prototyping having includes really helps things move along.

The hello world example can then be rewritten as;

load("fx:base.js");
load("fx:controls.js");
load("fx:graphics.js");
$STAGE.title = "Hello World!";
var button = new Button();
button.text = "Say 'Hello World'";
button.onAction = function() print("Hello World!");
var root = new StackPane();
root.children.add(button);
$STAGE.scene = new Scene(root, 300, 250);
$STAGE.show();

The complete set of includes are as follows;

fx:base.js

javafx.stage.Stage

javafx.scene.Scene

javafx.scene.Group

javafx/beans

javafx/collections

javafx/events

javafx/util
fx:graphics.js

javafx/animation

javafx/application

javafx/concurrent

javafx/css

javafx/geometry

javafx/print

javafx/scene

javafx/stage
fx:controls.js

javafx/scene/chart

javafx/scene/control
fx:fxml.js

javafx/fxml
fx:web.js

javafx/scene/web
fx:media.js

javafx/scene/media
fx:swing.js

javafx/embed/swing
fx:swt.js

javafx/embed/swt

Here are a couple more examples;

// fx3d.js
load("fx:base.js");
load("fx:controls.js");
load("fx:graphics.js");
var material = new PhongMaterial();
material.diffuseColor = Color.LIGHTGREEN;
material.specularColor = Color.rgb(30, 30, 30);
var meshView = Java.to([
new Box(200, 200, 200),
new Sphere(100),
new Cylinder(100, 200)
], "javafx.scene.shape.Shape3D[]");
for (var i = 0; i != 3; i++) {
meshView[i].material = material;
meshView[i].translateX = (i + 1) * 220;
meshView[i].translateY = 500;
meshView[i].translateZ = 20;
meshView[i].drawMode = DrawMode.FILL;
meshView[i].cullFace = CullFace.BACK;
};
var pointLight = new PointLight(Color.WHITE);
pointLight.translateX = 800;
pointLight.translateY = -200;
pointLight.translateZ = -1000;
var root = new Group(meshView);
root.children.add(pointLight);
var scene = new Scene(root, 800, 800, true);
scene.fill = Color.rgb(127, 127, 127);
scene.camera = new PerspectiveCamera(false);
$STAGE.scene = scene;
$STAGE.show();

// ColorfulCircles.js
load("fx:base.js");
load("fx:controls.js");
load("fx:graphics.js");
var WIDTH = 500;
var HEIGHT = 600;
var animation;
function setup(primaryStage) {
var root = new Group();
primaryStage.resizable = false;
var scene = new Scene(root, WIDTH, HEIGHT);
scene.title = "Colourful Circles";
primaryStage.scene = scene;
// create first list of circles
var layer1 = new Group();
for(var i = 0; i < 15; i++) {
var circle = new Circle(200, Color.web("white", 0.05));
circle.strokeType = StrokeType.OUTSIDE;
circle.stroke = Color.web("white", 0.2);
circle.strokeWidth = 4;
layer1.children.add(circle);
}
// create second list of circles
var layer2 = new Group();
for(var i = 0; i < 20; i++) {
var circle = new Circle(70, Color.web("white", 0.05));
circle.strokeType = StrokeType.OUTSIDE;
circle.stroke = Color.web("white", 0.1);
circle.strokeWidth = 2;
layer2.children.add(circle);
}
// create third list of circles
var layer3 = new Group();
for(var i = 0; i < 10; i++) {
var circle = new Circle(150, Color.web("white", 0.05));
circle.strokeType = StrokeType.OUTSIDE;
circle.stroke = Color.web("white", 0.16);
circle.strokeWidth = 4;
layer3.children.add(circle);
}
// Set a blur effect on each layer
layer1.effect = new BoxBlur(30, 30, 3);
layer2.effect = new BoxBlur(2, 2, 2);
layer3.effect = new BoxBlur(10, 10, 3);
// create a rectangle size of window with colored gradient
var colors = new Rectangle(WIDTH, HEIGHT,
new LinearGradient(0, 1, 1, 0, true, CycleMethod.NO_CYCLE,
new Stop(0, Color.web("#f8bd55")),
new Stop(0.14, Color.web("#c0fe56")),
new Stop(0.28, Color.web("#5dfbc1")),
new Stop(0.43, Color.web("#64c2f8")),
new Stop(0.57, Color.web("#be4af7")),
new Stop(0.71, Color.web("#ed5fc2")),
new Stop(0.85, Color.web("#ef504c")),
new Stop(1, Color.web("#f2660f"))));
colors.blendMode = BlendMode.OVERLAY;
// create main content
var group = new Group(new Rectangle(WIDTH, HEIGHT, Color.BLACK),
layer1,
layer2,
layer3,
colors);
var clip = new Rectangle(WIDTH, HEIGHT);
clip.smooth = false;
group.clip = clip;
root.children.add(group);
// create list of all circles
var allCircles = new java.util.ArrayList();
allCircles.addAll(layer1.children);
allCircles.addAll(layer2.children);
allCircles.addAll(layer3.children);
// Create a animation to randomly move every circle in allCircles
animation = new Timeline();
for each (var circle in allCircles) {
animation.getKeyFrames().addAll(
new KeyFrame(Duration.ZERO, // set start position at 0s
new KeyValue(circle.translateXProperty(), Math.random() * WIDTH),
new KeyValue(circle.translateYProperty(), Math.random() * HEIGHT)),
new KeyFrame(new Duration(20000), // set end position at 20s
new KeyValue(circle.translateXProperty(), Math.random() * WIDTH),
new KeyValue(circle.translateYProperty(), Math.random() * HEIGHT))
);
}
animation.autoReverse = true;
animation.cycleCount = Animation.INDEFINITE;
}
function stop() {
animation.stop();
}
function play() {
animation.play();
}
function start(primaryStage) {
setup(primaryStage);
primaryStage.show();
play();
}



Join the discussion

Comments ( 4 )
  • jlaskey Thursday, May 9, 2013

    This proposal has been approved and finalized by CCC.


  • David Conrad Monday, September 30, 2013

    It's necessary to make some changes to these scripts to get them to work with the latest nashorn build. The var Scene = Java.type("javafx.scene.Scene") syntax must be used for the imports, and for the fx3d.js script, the meshView should be a simple js array and each of its elements should be added to the Group with root.children.add(meshView[i]).


  • jlaskey Monday, September 30, 2013

    There are a couple issues that I've cleaned up in the code above. The var Scene = Java.type("javafx.scene.Scene") change is discretionary, but recommended (changed above.) The load("fx:base.js") call is broken in recent builds, which caused Scene to be undefined. Should be fixed in b112. The meshView issue is a matter of using Java.to instead of the deprecated Java.toArray.


  • FX Chronicles Sunday, June 29, 2014

    I agree with the majority of the points in this article and it’s great without any doubt. Really a <a href="http://fxchronicles.com//"> wonderful post! </a> I like it very much. Here I find everything in details. I hope I will see this type of post again in your blog.

    Thanks…….


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services