• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
JavaFX 2.0 With Alternative Languages - JavaOne 2011
 

JavaFX 2.0 With Alternative Languages - JavaOne 2011

on

  • 7,432 views

JavaFX 2.0 With Alternative Langauges Talk Given at JavaOne 2011 with Dean Iverson.

JavaFX 2.0 With Alternative Langauges Talk Given at JavaOne 2011 with Dean Iverson.

Covers ScalaFX, GroovyFX, Visage, and Clojure

Statistics

Views

Total Views
7,432
Views on SlideShare
7,411
Embed Views
21

Actions

Likes
2
Downloads
37
Comments
0

3 Embeds 21

http://paper.li 15
http://twitter.com 4
http://us-w1.rockmelt.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Stage.add??

JavaFX 2.0 With Alternative Languages - JavaOne 2011 JavaFX 2.0 With Alternative Languages - JavaOne 2011 Presentation Transcript

  • JavaFX 2.0 With Alternative Languages
    Stephen Chin
    Chief Agile Methodologist, GXS
    steveonjava@gmail.com
    tweet: @steveonjava
    Dean Iverson
    VTTI
    deanriverson@gmail.com
    tweet: @deanriverson
  • Meet the Presenters
    Stephen Chin
    Dean Iverson
    Family Man
    Family Man
    Motorcyclist
    Geek
  • Disclaimer: This is Code-Heavy
    THE FOLLOWING IS INTENDED TO STIMULATE CREATIVE USE OF JVM LANGUAGES. AFTER WATCHING THIS PRESENTATION YOU MAY FEEL COMPELLED TO START LEARNING A NEW JVM LANGUAGE. THE PRESENTERS ARE NOT LIABLE FOR ANY INNOVATION, BREAKTHROUGHS, OR NP-COMPLETE SOLUTIONS THAT MAY RESULT.
  • JavaFX With Java
  • Programming Languages
    JavaFX 2.0 APIs are now in Java
    Pure Java APIs for all of JavaFX
    Bindingand Sequences exposed as Java APIs
    FXML Markup for tooling
    Embrace all JVM languages
    Groovy, Scala, Clojure, JRuby
    Fantom, Mira, Gosu, Jython, etc.
    JavaFX Script is no longer supported by Oracle
    Existing JavaFX Script based applications will continue to run
    Visageis the open-source successor to the JavaFX Script language
  • JavaFX in Java
    JavaFX API uses an enhanced JavaBeans pattern
    Similar in feel to other UI toolkits (Swing, Apache Pivot, 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.show();
    }
    public static void main(String[] args) {
    launch(HelloStage.class, args);
    }
    }
  • Example Application Using Builders
    public class HelloStage extends Application {
    @Override public void start(Stage stage) {
    stage.setTitle("Hello Stage");
    stage.setScene(SceneBuilder.create()
    .fill(Color.LIGHTGREEN)
    .width(600)
    .height(450)
    .build());
    stage.show();
    }
    public static void main(String[] args) {
    launch(HelloStage.class, args);
    }
    }
  • Binding
    Unquestionably the biggest JavaFX Script innovation
    Supported via a PropertyBindingclass
    Lazy invocation for high performance
    Static construction syntax for simple cases
    e.g.: bind(<property>), bindBiDirectional(<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 Groovy
  • Features of Groovy
    Modern language
    Closures
    AST Transforms
    Strongly typed dynamic language
    Tight integration with Java
    Very easy to port from Java to Groovy
    Declarative syntax with GroovyFX Builders
    Familiar to Groovy and JavaFX Script developers
  • Java vs. GroovyFX DSL
    public 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);
    scene.setRoot(new Group(rect));
    stage.setScene(scene);
    stage.show();
    }
    public static void main(String[] args) {
    launch(HelloStage.class, args);
    }
    }
    GroovyFX.start { stage ->
    def sg = new SceneGraphBuilder(stage)
    sg.stage(title: “Hello Stage”, width: 600, height: 450) {
    scene(fill: groovyblue) {
    rectangle(x: 25, y: 40, width: 100, height: 50, fill: red)
    }
    }
    }
    19
    8 Lines
    180 Characters
    21 Lines
    430 Characters
  • def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    20
  • 21
    def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    Builder for GroovyFX scene graphs
  • 22
    def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    Declarative Stage definition
  • 23
    def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    Inline property definitions
  • 24
    def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    Bind to properties
  • 25
    def sg = new SceneGraphBuilder()
    def hc = { hover -> hover ? 4 : 0 }
    sg.stage(title: 'Vanishing Circles', show: true) {
    scene(fill: black, width: 800, height: 600) {
    50.times {
    circle(centerX: rand(800), centerY: rand(600),
    radius: 150, stroke: white,
    strokeWidth: bind('hover', converter: hc)) {
    fill rgb(rand(255), rand(255), rand(255), 0.2)
    effect boxBlur(width: 10, height: 10, iterations: 3)
    }
    }
    }
    }
    Sequence Creation Via Loop
  • Properties in Java
    public class Person {
    private StringPropertyfirstName;
    public void setFirstName(Stringval) { firstNameProperty().set(val); }
    public String getFirstName() { return firstNameProperty().get(); }
    public StringPropertyfirstNameProperty() {
    if (firstName == null)
    firstName = new SimpleStringProperty(this, "firstName");
    return firstName;
    }
    private StringPropertylastName;
    public void setLastName(String value) { lastNameProperty().set(value); }
    public String getLastName() { return lastNameProperty().get(); }
    public StringPropertylastNameProperty() {
    if (lastName == null) // etc.
    }
    }
    26
  • Properties in GroovyFX
    public class Person {
    @FXBindable String firstName;
    @FXBindable String lastName;
    }
    27
  • public class Person {
    @FXBindable String firstName;
    @FXBindable String lastName= “Smith”;
    }
    Properties in GroovyFX
    28
    Optional initializers
  • public class Person {
    @FXBindable String firstName;
    @FXBindable String lastName = “Smith”;
    }
    def p = new Person()
    def last = p.lastName
    p.firstName = “Agent”
    Properties in GroovyFX
    29
    Get and set values
  • public class Person {
    @FXBindable String firstName;
    @FXBindable String lastName = “Smith”;
    }
    def p = new Person()
    def last = p.lastName
    p.firstName = “Agent”
    textField(text: bind(p.lastNameProperty()))
    Properties in GroovyFX
    30
    Access underlying property for binding
  • Binding in GroovyFX
    @FXBindable
    class Time {
    Integer hours
    Integer minutes
    Integer seconds
    Double hourAngle
    Double minuteAngle
    Double secondAngle
    public Time() {
    // bind the angle properties to the clock time
    hourAngleProperty().bind((hoursProperty() * 30.0) + (minutesProperty() * 0.5))
    minuteAngleProperty().bind(minutesProperty() * 6.0)
    secondAngleProperty().bind(secondsProperty() * 6.0)
    }
    }
    31
  • Animation in GroovyFX
    timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
    at (1000.ms) {
    change(rect1, 'x') to 200 tweenease_both
    change rect2.yProperty() to 200 tween linear
    }
    }.play()
    32
  • timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
    at (1000.ms) {
    change(rect1, 'x') to 200 tweenease_both
    change rect2.yProperty() to 200 tween linear
    }
    }.play()
    Animation in GroovyFX
    33
    Easy animation syntax:
    at (duration) {keyframes}
  • timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
    at (1000.ms) {
    change(rect1, 'x') to 200
    change rect2.yProperty() to 200
    }
    }.play()
    Animation in GroovyFX
    34
    Key frame DSL
  • timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
    at (1000.ms) {
    change(rect1, 'x') to 200 tweenease_both
    change rect2.yProperty() to 200tween linear
    }
    }.play()
    Animation in GroovyFX
    35
    Optional easing
  • Event Listeners in GroovyFX
    36
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    onMouseClicked { e ->
    timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
    }.play()
    }
  • Event Listeners in GroovyFX
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    37
    onMouseClicked {MouseEvente ->
    timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
    }.play()
    }
    Compact syntax
    {body}
  • Event Listeners in GroovyFX
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    38
    Optional event parameter
    {event -> body}
    onMouseClicked { MouseEvente ->
    timeline {
    at(3.s) { change e.source.radiusProperty() to 0 }
    }.play()
    }
  • TableView in Java
    39
    ObservableList<Person> items = ...
    TableView<Person> tableView = new TableView<Person>(items);
    TableColumn<Person,String> firstNameCol =
    new TableColumn<Person,String>("First Name");
    firstNameCol.setCellValueFactory(
    new Callback<CellDataFeatures<Person, String>,
    ObservableValue<String>>() {
    public ObservableValue<String> call(CellDataFeatures<Person, String> p)
    {
    return p.getValue().firstNameProperty();
    }
    });
    tableView.getColumns().add(firstNameCol);
  • TableView in GroovyFX
    40
    def dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    tableView(items: persons) {
    tableColumn(property: "name", text: "Name", prefWidth: 150)
    tableColumn(property: "age", text: "Age", prefWidth: 50)
    tableColumn(property: "gender", text: "Gender", prefWidth: 150)
    tableColumn(property: "dob", text: "Birth", prefWidth: 150,
    type: Date,
    converter: { from -> return dateFormat.format(from) })
    }
  • Layout in Java
    41
    TextFieldurlField = new TextField(“http://www.google.com”);
    HBox.setHgrow(urlField, Priority.ALWAYS);
    HBoxhbox = new HBox();
    hbox.getChildren().add(urlField);
    WebViewwebView = new WebView();
    VBox.setVgrow(webView, Priority.ALWAYS);
    VBoxvbox = new VBox();
    vbox.getChildren().addAll(hbox, webView);
  • Layout in GroovyFX
    42
    sg.stage(title: "GroovyFXWebView Demo", show: true) {
    scene(fill: groovyblue, width: 1024, height: 800) {
    vbox{
    hbox(padding: 10, spacing: 5) {
    textField(“http://www.yahoo.com”, hgrow: "always")
    button("Go”)
    }
    webView(vgrow: "always")
    }
    }
    }
  • Layout in GroovyFX
    43
  • Layout in GroovyFX
    44
    gridPane(hgap: 5, vgap: 10, padding: 25) {
    columnConstraints(minWidth: 50, halignment: "right")
    columnConstraints(prefWidth: 250)
    label("Send Us Your Feedback", font: "24pt sanserif",
    row: 0, columnSpan: GridPane.REMAINING, halignment: "center",
    margin: [0, 0, 10])
    label("Name: ", row: 1, column: 0)
    textField(promptText: "Your name", row: 1, column: 1, hgrow: 'always')
    label("Email:", row: 2, column: 0)
    textField(promptText: "Your email", row: 2, column: 1, hgrow: 'always')
    label("Message:", row: 3, column: 0, valignment: "baseline")
    textArea(row: 3, column: 1, hgrow: "always", vgrow: "always")
    button("Send Message", row: 4, column: 1, halignment: "right")
    }
  • Layout in GroovyFX
    45
  • GroovyFX Supports…
    46
  • GroovyFX Supports…
    47
  • 48
    JavaFX With Clojure
    Artwork by Augusto Sellhorn
    http://sellmic.com/
  • 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!
    49
    (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}
    50
    (plus macros that are syntactic sugar wrapping the above)
  • Clojure GUI Example
    (defnjavafxapp []
    (let [stage (Stage. "JavaFX Stage")
    scene (Scene.)]
    (.setFill scene Color/LIGHTGREEN)
    (.setWidth stage 600)
    (.setHeight stage 450)
    (.setScene stage scene)
    (.setVisible stage true)))
    (javafxapp)
    51
  • Refined Clojure GUI Example
    (defnjavafxapp []
    (doto (Stage. "JavaFX Stage")
    (.setWidth600)
    (.setHeight450)
    (.setScene (doto (Scene.)
    (.setFillColor/LIGHTGREEN)
    (.setContent (list (doto (Rectangle.)
    (.setX25)
    (.setY40)
    (.setWidth100)
    (.setHeight50)
    (.setFillColor/RED))))))
    (.setVisibletrue)))
    (javafxapp)
    52
  • Refined Clojure GUI Example
    (defnjavafxapp []
    (doto (Stage. "JavaFX Stage")
    (.setWidth 600)
    (.setHeight 450)
    (.setScene (doto (Scene.)
    (.setFillColor/LIGHTGREEN)
    (.setContent (list (doto (Rectangle.)
    (.setX 25)
    (.setY 40)
    (.setWidth 100)
    (.setHeight 50)
    (.setFillColor/RED))))))
    (.setVisible true)))
    (javafxapp)
    53
    Doto allows nested data structures
  • Closures in Clojure
    54
    Inner classes can be created using proxy
    (.addListenerhoverProperty
    (proxy [ChangeListener] []
    (handle [p, o, v]
    (.setFillrect
    (if (.isHoverrect) Color/GREEN Color/RED)))))
  • Closures in Clojure
    Inner classes can be created using proxy
    55
    Proxy form:
    (proxy [class] [args] fs+)
    f => (name [params*] body)
    (.addListenerhoverProperty
    (proxy[ChangeListener][]
    (handle [p, o, v]
    (.setFillrect
    (if (.isHoverrect) Color/GREEN Color/RED)))))
  • 56
    JavaFX With Scala
  • What is Scala
    Started in 2001 by Martin Odersky
    Compiles to Java bytecodes
    Pure object-oriented language
    Also a functional programming language
    57
  • 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 Type Safe DSLs!
    Implicit Conversions – type safe class extension
    Operator Overloading – with standard precedence rules
    DelayedInit / @specialized – advanced language features
    58
  • Java vs. Scala DSL
    public 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);
    scene.setRoot(new Group(rect));
    stage.setScene(scene);
    stage.show();
    }
    public static void main(String[] args) {
    launch(HelloStage.class, args);
    }
    }
    object HelloJavaFX extends JFXApp {
    stage = new Stage {
    title = "Hello Stage"
    width = 600
    height = 450
    scene = new Scene {
    fill = LIGHTGREEN
    content = Seq(new Rectangle {
    x = 25
    y = 40
    width = 100
    height = 50
    fill = RED
    })
    }
    }
    }
    59
    21 Lines
    430 Characters
    17 Lines
    177 Characters
  • object DisappearingCirclesextends JFXApp {
    stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
    fill = BLACK
    content = for (i <- 0 until 50) yield new Circle {
    centerX = random * 800
    centerY = random * 600
    radius = 150
    fill = color(random, random, random, 0.2)
    effect = new BoxBlur(10, 10, 3)
    }
    }
    }
    }
    60
  • 61
    object DisappearingCirclesextends JFXApp{
    stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
    fill = BLACK
    content = for (i <- 0 until 50) yield new Circle {
    centerX = random * 800
    centerY = random * 600
    radius = 150
    fill = color(random, random, random, 0.2)
    effect = new BoxBlur(10, 10, 3)
    }
    }
    }
    }
    Base class for JavaFX applications
  • 62
    object DisappearingCirclesextends JFXApp {
    stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
    fill = BLACK
    content = for (i <- 0 until 50) yield new Circle {
    centerX = random * 800
    centerY = random * 600
    radius = 150
    fill = color(random, random, random, 0.2)
    effect = new BoxBlur(10, 10, 3)
    }
    }
    }
    }
    Declarative Stage definition
  • 63
    object DisappearingCirclesextends JFXApp {
    stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
    fill = BLACK
    content = for (i <- 0 until 50) yield new Circle {
    centerX = random * 800
    centerY = random * 600
    radius = 150
    fill = color(random, random, random, 0.2)
    effect = new BoxBlur(10, 10, 3)
    }
    }
    }
    }
    Inline property definitions
  • 64
    object DisappearingCirclesextends JFXApp {
    stage = new Stage {
    title = "Disappearing Circles"
    width = 800
    height = 600
    scene = new Scene {
    fill = BLACK
    content = for (i <- 0 until 50) yield new Circle {
    centerX = random * 800
    centerY = random * 600
    radius = 150
    fill = color(random, random, random, 0.2)
    effect = new BoxBlur(10, 10, 3)
    }
    }
    }
    }
    Sequence Creation Via Loop
  • Binding in Scala
    Infix Addition/Subtraction/Multiplication/Division:
    height <== rect1.height + rect2.height
    Aggregate Operators:
    width <== max(rect1.width, rect2.width, rect3.width)
    Conditional Expressions:
    strokeWidth <== when (hover) then 4 otherwise 0
    Compound Expressions:
    text <== when (rect.hover || circle.hover && !disabled) then textField.text + " is enabled" otherwise "disabled"
    65
  • Animation in Scala
    valtimeline = new Timeline {
    cycleCount = INDEFINITE
    autoReverse = true
    keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
    circle.centerX -> random * stage.width,
    circle.centerY -> random * stage.height
    )
    }
    }
    timeline.play();
    66
  • valtimeline = new Timeline {
    cycleCount = INDEFINITE
    autoReverse = true
    keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
    circle.centerX -> random * stage.width,
    circle.centerY -> random * stage.height
    )
    }
    }
    timeline.play();
    Animation in Scala
    67
    JavaFX Script-like animation syntax: at (duration) {keyframes}
  • valtimeline = new Timeline {
    cycleCount = INDEFINITE
    autoReverse = true
    keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
    circle.centerX -> random * stage.width,
    circle.centerY -> random * stage.height
    )
    }
    }
    timeline.play();
    Animation in Scala
    68
    Operator overloading for animation syntax
  • valtimeline = new Timeline {
    cycleCount = INDEFINITE
    autoReverse = true
    keyFrames = for (circle <- circles) yield at (40 s) {
    Set(
    circle.centerX-> random * stage.widthtween EASE_BOTH,
    circle.centerY-> random * stage.heighttween EASE_IN
    )
    }
    }
    timeline.play();
    Animation in Scala
    69
    Optional tween syntax
  • Event Listeners in Scala
    70
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    100% type-safe
    onMouseClicked= {
    Timeline(at(3 s){radius->0}).play()
    }
  • Event Listeners in Scala
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    100% type-safe
    71
    onMouseClicked= {
    Timeline(at(3 s){radius->0}).play()
    }
    Compact syntax
    {body}
  • Event Listeners in Scala
    Supported using the built-in Closure syntax
    Optional arguments for event objects
    100% type-safe
    72
    Optional event parameter
    {(event) => body}
    onMouseClicked= { (e: MouseEvent) =>
    Timeline(at(3 s){radius->0}).play()
    }
  • Other JVM Languages to Try
    JRuby
    Faithful to Ruby language with the power of the JVM
    Gosu
    Up and coming language created at GuideWire
    Easy to enhance libraries and create DSLs
    Mirah
    Invented by Charles Nutter
    Local Type Inference, Static and Dynamic Typing
    Fantom
    Created by Brian and Andy Frank
    Portable to Java and .NET
    Local Type Inference, Static and Dynamic Typing
    73
  • 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
    }
    74
  • 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
    75
    Fantom has a built-in Duration type
    And also supports operator overloading
  • About Project Visage
    76
    • “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.”
    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/
  • 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
    }
    }
    }
    77
  • 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
    }
    }
    }
    78
  • 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
    }
    }
    }
    79
  • Visage is JavaFX Script++
    Default Parameters
    New Literal Syntax For:
    Angles – 35deg, 4rad, 1turn
    Colors –#DDCCBB, #AA33AA|CC
    Lengths – 5px, 2pt, 3in, 4sp
    Null-check Dereference
    var width = rect.!width
    Built-in Bindable Maps (coming soon!)
    varfruitMap = ["red" : apple, "yellow" : banana]
    var fruit = bind fruitMap["red"]
    80
  • Visage and JavaFX 2.0 are made for each other…
    Enhanced Binding
    Retains lazy evaluation properties with additional expressive power
    Integrated Collections
    Sequences and Maps automatically convert between JavaFX Observable Lists/Maps
    Built-in Animation Syntax
    Ties into JavaFX animation subsystem
    Provides consistent, clean APIs
    81
  • Conclusion
    You can write JavaFX applications in pure Java
    JavaFX is also usable in alternate languages
    You can get improved support using DSL libraries
    GroovyFX
    ScalaFX
    Or a dedicated UI JVM Language
    Visage
  • Pro JavaFX 2 Platform Coming Soon!
    Coming 4th quarter this year
    All examples rewritten in Java
    Covers the new JavaFX 2.0 APIs
    Will includes ScalaFX, GroovyFX, and Visage
    83
  • 84
    Stephen Chin
    steveonjava@gmail.com
    tweet: @steveonjava
    Dean Iverson
    dean@pleasingsoftware.com
    tweet: @deanriverson