Upload
stephen-chin
View
4.797
Download
2
Tags:
Embed Size (px)
DESCRIPTION
Presentation given at Jazoon on using JavaFX with alternative languages. Includes updates for GroovyFX and the JavaFX 2.0 Beta.
Citation preview
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and Visage Stephen ChinChief Agile Methodologist, [email protected]: @steveonjava
About the Presenter
Stephen Chin
Motorcyclist
Family ManChief Agile Methodologist, GXS
Author, Pro JavaFX Platform
Java Champion
OSCON Java Conference Chair
Pro JavaFX 2 Platform Coming Soon!
> Coming 2nd half of this year> All examples rewritten in Java> Will cover the new JavaFX 2.0
APIs
3
Disclaimer: This is code-heavy
JavaFX With Java
JavaFX 2.0 Product Timeline
CYQ1 2011
JavaFX 2.0 EA(Early Access)
CYQ2 2011 CYQ3 2011
JavaFX 2.0 Beta JavaFX 2.0 GA(General Availability)
Copyright 2010 Oracle
JavaFX Beta Available Now!
Programming Languages
> JavaFX 2.0 APIs are now in Java Pure Java APIs for all of JavaFX Expose JavaFX Binding, Sequences as Java APIs
> Embrace all JVM languages JRuby, Clojure, Groovy, Scala Fantom, Mira, Jython, etc.
> JavaFX Script is no longer supported by Oracle Existing JavaFX Script based applications will
continue to run Visage is the open-source successor to the JavaFX
Script language
JavaFX in Java
> JavaFX API follows JavaBeans approach
> Similar in feel to other UI toolkits (Swing, etc)
> Uses builder pattern to minimize boilerplate
Example Application
public class HelloStage extends Application {
@Override public void start(Stage stage) { stage.setTitle("Hello Stage"); stage.setWidth(600); stage.setHeight(450);
Group root = new Group(); Scene scene = new Scene(root); scene.setFill(Color.LIGHTGREEN);
stage.setScene(scene); stage.setVisible(true); }
public static void main(String[] args) { launch(HelloStage.class, args); }}
Binding
> Unquestionably the biggest JavaFX Script innovation
> Supported via a PropertyBinding class
> Lazy invocation for high performance
> Static construction syntax for simple cases e.g.: bindTo(<property>)
Observable Pseudo-Properties
> Supports watching for changes to properties
> Implemented via anonymous inner classes
> Will take advantage of closures in the future
Observable Pseudo-Properties
final Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);
rect.hoverProperty().addListener(new ChangeListener<Boolean>() {
});
Observable Pseudo-Properties
final Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);
rect.hoverProperty().addListener(new ChangeListener<Boolean>() {
});
The property we want to watch
Observable Pseudo-Properties
final Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);
rect.hoverProperty().addListener(new ChangeListener<Boolean>() {
});
Only one listener used with generics to specify the data type
Observable Pseudo-Properties
final Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);
rect.hoverProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean value) {
}});
Refers to the Rectangle.hoverProperty()
Observable Pseudo-Properties
final Rectangle rect = new Rectangle();rect.setX(40);rect.setY(40);rect.setWidth(100);rect.setHeight(200);
rect.hoverProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean value) { rect.setFill(rect.isHover() ? Color.GREEN : Color.RED); }});
Sequences in Java
> Replaced with an Observable List
> Public API is based on JavaFX sequences
> Internal code can use lighter collections API
> JavaFX 2.0 also has an Observable Map
JavaFX With JRuby
Why JRuby?
> Direct access to Java APIs
> Dynamic Typing
> Closures> ‘Closure conversion’ for interfaces
Java in JRuby - Accessing Properties
timeline.setAutoReverse(true)timeline.autoReverse = truetimeline.auto_reverse = true
timeline.getKeyFrames().add(kf)timeline.key_frames.add(kf)timeline.key_frames.add kf
JRuby Example 1: Simple Stage
require 'java'
Application = Java::javafx.application.ApplicationStage = Java::javafx.stage.StageScene = Java::javafx.scene.SceneColor = Java::javafx.scene.paint.Color
class HelloStage < Application
def start(stage) ..... endend
Application.launch(HelloStage.new);
stage.title = 'Hello Stage (JRuby)'stage.width = 600stage.height = 450
scene = Scene.newscene.fill = Color::LIGHTGREENstage.scene = scene
stage.visible = true;
JRuby Example 2
rect = Rectangle.newrect.x = 25rect.y = 40rect.width = 100rect.height = 50rect.fill = Color::REDroot.children.add(rect)
timeline = Timeline.newtimeline.cycle_count = Timeline::INDEFINITEtimeline.auto_reverse = truekv = KeyValue.new(rect.xProperty, 200);kf = KeyFrame.new(Duration.valueOf(500), kv);timeline.key_frames.add kf;timeline.play();
JRuby Closure Conversion
rect.hoverProperty.addListener() do |prop, oldVal, newVal| rect.fill = rect.hover ? Color::GREEN : Color::RED;end
23
JRuby Swiby
require 'swiby'
class HelloWorldModel attr_accessor :sayingendmodel = HelloWorldModel.new model.saying = "Hello World"
Frame { title "Hello World“ width 200 content { Label { text bind(model,:saying) } } visible true}
24
25
JavaFX With Clojure
Artwork by Augusto Sellhorn http://sellmic.com/
26
A Little About Clojure
> Started in 2007 by Rich Hickey> Functional Programming Language> Derived from LISP> Optimized for High Concurrency
> … and looks nothing like Java!
(def hello (fn [] "Hello world"))(hello)
Clojure Syntax in One Slide
Symbols
> numbers – 2.178> ratios – 355/113> strings – “clojure”, “rocks”> characters – \a \b \c \d> symbols – a b c d> keywords – :alpha :beta> boolean – true, false> null - nil
Collections(commas optional)
> Lists(1, 2, 3, 4, 5)> Vectors[1, 2, 3, 4, 5]> Maps{:a 1, :b 2, :c 3, :d 4}> Sets#{:a :b :c :d :e}
27
(plus macros that are syntactic sugar wrapping the above)
Clojure GUI Example
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true)))(javafxapp)
28
Clojure GUI Example
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true)))(javafxapp)
29
Create a Function for the Application
Clojure GUI Example
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true)))(javafxapp)
30
Initialize the Stage and Scene Variables
Clojure GUI Example
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true)))(javafxapp)
31
Call Setter Methods on Scene and Stage
Clojure GUI Example
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (.setFill scene Color/LIGHTGREEN) (.setWidth stage 600) (.setHeight stage 450) (.setScene stage scene) (.setVisible stage true)))(javafxapp)
32
Java Constant Syntax
Java Method Syntax
Simpler Code Using doto
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (doto scene (.setFill Color/LIGHTGREEN)) (doto stage (.setWidth 600) (.setHeight 450) (.setScene scene) (.setVisible true))))(javafxapp)
33
Simpler Code Using doto
(defn javafxapp [] (let [stage (Stage. "JavaFX Stage") scene (Scene.)] (doto scene (.setFill Color/LIGHTGREEN)) (doto stage (.setWidth 600) (.setHeight 450) (.setScene scene) (.setVisible true))))(javafxapp)
34
doto form: (doto symbol (.method params)) equals: (.method symbol params)
Refined Clojure GUI Example
(defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) (.setHeight 450) (.setScene (doto (Scene.) (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true)))(javafxapp)
35
Refined Clojure GUI Example
(defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) (.setHeight 450) (.setScene (doto (Scene.) (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true)))(javafxapp)
36
Let replaced with inline declarations
Refined Clojure GUI Example
(defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) (.setHeight 450) (.setScene (doto (Scene.) (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true)))(javafxapp)
37
Doto allows nested data structures
Refined Clojure GUI Example
(defn javafxapp [] (doto (Stage. "JavaFX Stage") (.setWidth 600) (.setHeight 450) (.setScene (doto (Scene.) (.setFill Color/LIGHTGREEN) (.setContent (list (doto (Rectangle.) (.setX 25) (.setY 40) (.setWidth 100) (.setHeight 50) (.setFill Color/RED)))))) (.setVisible true)))(javafxapp)
38
Now a nested Rectangle fits!
Closures in Clojure
39
> Inner classes can be created using proxy
(.addListener hoverProperty (proxy [ChangeListener] [] (changed [p, o, v] (.setFill rect (if (.isHover rect) Color/GREEN Color/RED)))))
Closures in Clojure
> Inner classes can be created using proxy
40
(.addListener hoverProperty (proxy [ChangeListener] [] (changed [p, o, v] (.setFill rect (if (.isHover rect) Color/GREEN Color/RED)))))
Proxy form: (proxy [class] [args] fs+) f => (name [params*] body)
JavaFX With Groovy
Features of Groovy
> Tight integration with Java Very easy to port from Java to Groovy
> Declarative syntax Familiar to JavaFX Script developers
> Builders
Step 1: Lazy conversion to Groovy
class HelloStage extends Application {
void start(stage) { stage.setTitle("Hello Stage (Groovy)"); stage.setWidth(600); stage.setHeight(450);
Group root = new Group(); Scene scene = new Scene(root); scene.setFill(Color.LIGHTSKYBLUE);
stage.setScene(scene); stage.setVisible(true); }
static void main(args) { launch(HelloStage.class, args); }}
Step 2: Slightly More Groovy
class HelloStage extends Application {
void start(stage) { stage.setTitle("Hello Stage (Groovy)"); stage.setScene(new Scene( width: 600, height: 450, fill: Color.LIGHTSKYBLUE root: new Group() )); stage.setVisible(true); }
static void main(args) { launch(HelloStage.class, args); }}
Introducing GroovyFX
> Groovy DSL for JavaFX> Started by James Clark> In Alpha 1.0 State
http://groovy.codehaus.org/GroovyFX
Step 3: Using GroovyFX
GroovyFX.start ({ def sg = new SceneGraphBuilder(); def stage = sg.stage( title: "Hello World", width: 600, height: 450, visible: true ) { scene(fill: Color.LIGHTSKYBLUE) { ... } )}
Step 4: With Content
GroovyFX.start ({ def sg = new SceneGraphBuilder(); def stage = sg.stage( title: "Hello World", width: 600, height: 450, visible: true ) { scene(fill: Color.LIGHTSKYBLUE) { rectangle( x: 25, y: 40, width: 100, height: 50, fill: Color.RED )})}
FX Script Animation in Groovy
Step 1: JavaFX Script
def timeline = Timeline { repeatCount: Timeline.INDEFINITE autoReverse: true keyFrames: [ KeyFrame { time: 750ms values : [ rect1.x => 200.0 tween Interpolator.LINEAR, rect2.y => 200.0 tween Interpolator.LINEAR, circle1.radius => 200.0 tween Interpolator.LINEAR ] } ];}
timeline.play();
Step 1a: JavaFX Script Simplificationdef timeline = Timeline { repeatCount: Timeline.INDEFINITE autoReverse: true keyFrames: at (750ms) { rect1.x => 200.0 tween Interpolator.LINEAR; rect2.y => 200.0 tween Interpolator.LINEAR; circle1.radius => 200.0 tween Interpolator.LINEAR; }}
timeline.play();
Step 2: Java-ish Groovy Animations
final Timeline timeline = new Timeline( cycleCount: Timeline.INDEFINITE, autoReverse: true)
final KeyValue kv1 = new KeyValue (rect1.xProperty(), 200);final KeyValue kv2 = new KeyValue (rect2.yProperty(), 200);final KeyValue kv3 = new KeyValue (circle1.radiusProperty(), 200);
final KeyFrame kf = new KeyFrame(Duration.valueOf(750), kv1, kv2, kv3);
timeline.getKeyFrames().add(kf);
timeline.play();
Step 3: GroovyFX Animation
timeline = timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
at 750.ms { change (rect1, "y") { to 200 } change (rect2, "x") { to 200 } change (circle, "radius") { to 200 } }}
timeline.play();
Groovy Closures - With interface coercion
def f = { p, o, v -> rect.setFill(rect.isHover() ? Color.GREEN : Color.RED);} as ChangeListener;
rect.hoverProperty().addListener(f);
54
JavaFX With Scala
55
What is Scala
> Started in 2001 by Martin Odersky> Compiles to Java bytecodes> Pure object-oriented language> Also a functional programming language
2001• Scala Started
2003/2004• Scala v1.0
2006• Scala v2.0
2011• Scala 2.9.0.1
(latest)
56
Why Scala?
> Shares many language features with JavaFX Script that make GUI programming easier: Static type checking – Catch your errors at compile
time Closures – Wrap behavior and pass it by reference Declarative – Express the UI by describing what it
should look like> Scala also supports DSLs!
Java vs. Scala DSLpublic class HelloStage extends Application
{
public void start(Stage stage) { stage.setTitle("Hello Stage"); stage.setWidth(600); stage.setHeight(450); Scene scene = new Scene(); scene.setFill(Color.LIGHTGREEN); Rectangle rect = new Rectangle(); rect.setX(25); rect.setY(40); rect.setWidth(100); rect.setHeight(50); rect.setFill(Color.RED); stage.add(rect); stage.setScene(scene); stage.setVisible(true); }
public static void main(String[] args) { Launcher.launch(HelloStage.class, args); }}
object HelloJavaFX extends JavaFXApplication {
def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
57
21 Lines541 Characters
17 Lines324 Characters
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
58
59
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
Base class for JavaFX applications
60
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
Declarative Stage definition
61
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
Inline property definitions
62
object HelloJavaFX extends JavaFXApplication { def stage = new Stage { title = "Hello Stage" width = 600 height = 450 scene = new Scene { fill = Color.LIGHTGREEN content = List(new Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED }) } }}
List Construction Syntax
Animation in Scala
def timeline = new Timeline { repeatCount = INDEFINITE autoReverse = true keyFrames = List( new KeyFrame(time: 50) { values = List( new KeyValue(rect1.xProperty -> 300), new KeyValue(rect2.yProperty -> 500), new KeyValue(rect2.widthProperty -> 150) ) } ) }
63
def timeline = new Timeline { repeatCount = INDEFINITE autoReverse = true keyFrames = List( new KeyFrame(time: 50) { values = List( new KeyValue(rect1.xProperty -> 300), new KeyValue(rect2.yProperty -> 500), new KeyValue(rect2.widthProperty -> 150) ) } ) }
Animation in Scala
64
Duration set by Constructor Parameter
Animation in Scala
65
Operator overloading for animation syntax
def timeline = new Timeline { repeatCount = INDEFINITE autoReverse = true keyFrames = List( new KeyFrame(time: 50) { values = List( new KeyValue(rect1.xProperty -> 300), new KeyValue(rect2.yProperty -> 500), new KeyValue(rect2.widthProperty -> 150) ) } ) }
Closures in Scala
66
> Closures are also supported in Scala> And they are 100% type-safe
rect.hoverProperty.addListener((p, o, v) => { rect.fill = if (rect.hover) Color.GREEN else Color.RED
})
Closures in Scala
> Closures are also supported in Scala> And they are 100% type-safe
67
Compact syntax(params) => {body}
rect.hoverProperty.addListener((p, o, v) => { rect.fill = if (rect.hover) Color.GREEN else Color.RED
})
Other JVM Languages to Try
> Jython Started by Jim Hugunin High Performance Python
> Mirah Invented by Charles Nutter Originally called Duby Local Type Inference, Static and Dynamic Typing
> Fantom Created by Brian and Andy Frank Originally called Fan Built-in Declarative Syntax Portable to Java and .NET Local Type Inference, Static and Dynamic Typing
68
Fantom Code Example
Void main() { Stage { title = "Hello Stage" width = 600 height = 450 Scene { fill = Color.LIGHTGREEN Rectangle { x = 25 y = 40 width = 100 height = 50 fill = Color.RED } } }.open}
69
timeline := Timeline { repeatCount = Timeline.INDEFINITE autoReverse = true KeyFrame { time = 50ms KeyValue(rect1.x() -> 300), KeyValue(rect2.y() -> 500), KeyValue(rect2.width() -> 150) }}
Animation in Fantom
70
Fantom has a built-in Duration type
And also supports operator overloading
Announcing Project Visage
71
> Visage project goals: Compile to JavaFX Java APIs Evolve the Language (Annotations, Maps, etc.) Support Other Toolkits
> Come join the team!> For more info: http://visage-lang.org/
> “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.”
How about JavaFX on… Visage
Stage { title: "Hello Stage" width: 600 height: 450 scene: Scene { fill: Color.LIGHTGREEN content: Rectangle { x: 25 y: 40 width: 100 height: 50 fill: Color.RED } }}
72
How about JavaFX on… Visage
Stage { title: "Hello Stage" width: 600 height: 450 scene: Scene { fill: Color.LIGHTGREEN content: Rectangle { x: 25 y: 40 width: 100 height: 50 fill: Color.RED } }}
73
How about JavaFX on… Visage
Stage { title: "Hello Stage" width: 600 height: 450 Scene { fill: Color.LIGHTGREEN Rectangle { x: 25 y: 40 width: 100 height: 50 fill: Color.RED } }}
74
Visage on Android
> Curious?
> Drop by room 4 after this talk to find out more…
Conclusion
> You can write JavaFX applications in pure Java> JavaFX is also usable in alternate languages> Over time improved support is possible
Groovy Builders, Scala DSL, Visage