[フレーム]
PPTX, PDF7,169 views

JavaFX and Scala - Like Milk and Cookies

The document discusses the integration of JavaFX with Scala, highlighting the features of JavaFX 2.0, such as cross-platform capabilities and a new graphics stack for enhanced performance. It provides examples of creating a 'vanishing circles' application using both Java and Scala, showcasing the use of timelines, animations, and event handling. The text also mentions Scalafx, which offers cleaner APIs for Scala programmers to utilize JavaFX more effectively.

Downloaded 69 times
14 / 46
Java vs. Scala DSL public class VanishingCircles extends Application { object VanishingCircles extends JFXApp { var circles: Seq[Circle] = null public static void main(String[] args) { stage = new Stage { Application.launch(args); title = "Vanishing Circles" } width = 800 height = 600 @Override scene = new Scene { public void start(Stage primaryStage) { fill = BLACK primaryStage.setTitle("Vanishing Circles"); circles = for (i <- 0 until 50) yield new Circle { Group root = new Group(); centerX = random * 800 Scene scene = new Scene(root, 800, 600, Color.BLACK); centerY = random * 600 List<Circle> circles = new ArrayList<Circle>(); radius = 150 for (int i = 0; i < 50; i++) { fill = color(random, random, random, .2) final Circle circle = new Circle(150); effect = new BoxBlur(10, 10, 3) 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); 33 Lines strokeWidth <== when (hover) then 4 otherwise 0 stroke = WHITE onMouseClicked = { Timeline(at (3 s) {radius -> 0}).play() 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); } } } 591 Characters content = circles new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } }); new Timeline { circle.setStroke(Color.WHITE); cycleCount = INDEFINITE circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) autoReverse = true .then(4) keyFrames = for (circle <- circles) yield at (40 s) { .otherwise(0)); Set( circles.add(circle); circle.centerX -> random * stage.width, } circle.centerY -> random * stage.height root.getChildren().addAll(circles); ) primaryStage.setScene(scene); } primaryStage.show(); }.play(); } Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 14
JavaFX and Scala – Like Milk and Cookies Stephen Chin Luc Duponcheel JavaFX Evangelist, Oracle Independent, ImagineJ steveonjava@gmail.com luc.duponcheel@gmail.com tweet: @steveonjava tweet: @LucDup
Meet the Presenters Stephen Chin Luc Duponcheel Family Man Motorcyclist BeJUG Researcher
JavaFX 2.0 Platform Immersive Application Experience > Cross-platform Animation, Video, Charting > Integrate Java, JavaScript, and HTML5 in the same application > New graphics stack takes advantage of hardware acceleration for 2D and 3D applications > Use your favorite IDE: NetBeans, Eclipse, IntelliJ, etc.
JavaFX Scala 4
JavaFX With Java
JavaFX in Java > JavaFX API uses an enhanced JavaBeans pattern > Similar in feel to other UI toolkits (Swing, Pivot, etc.) > Uses builder pattern to minimize boilerplate
Vanishing Circles 7
Application Skeleton public class VanishingCircles extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Vanishing Circles"); Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); [create the circles...] root.getChildren().addAll(circles); primaryStage.setScene(scene); primaryStage.show(); [begin the animation...] } }
Create the Circles List<Circle> circles = new ArrayList<Circle>(); for (int i = 0; i < 50; i++) { final Circle circle = new Circle(150); circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); circle.setStroke(Color.WHITE); [setup binding...] [setup event listeners...] circles.add(circle); } 9
Setup Binding circle.strokeWidthProperty().bind(Bindings .when(circle.hoverProperty()) .then(4) .otherwise(0) ); 10
Setup Event Listeners circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } }); 11
Begin the Animation Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); 12
JavaFX With Scala 13
Java vs. Scala DSL public class VanishingCircles extends Application { object VanishingCircles extends JFXApp { var circles: Seq[Circle] = null public static void main(String[] args) { stage = new Stage { Application.launch(args); title = "Vanishing Circles" } width = 800 height = 600 @Override scene = new Scene { public void start(Stage primaryStage) { fill = BLACK primaryStage.setTitle("Vanishing Circles"); circles = for (i <- 0 until 50) yield new Circle { Group root = new Group(); centerX = random * 800 Scene scene = new Scene(root, 800, 600, Color.BLACK); centerY = random * 600 List<Circle> circles = new ArrayList<Circle>(); radius = 150 for (int i = 0; i < 50; i++) { fill = color(random, random, random, .2) final Circle circle = new Circle(150); effect = new BoxBlur(10, 10, 3) 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); 33 Lines strokeWidth <== when (hover) then 4 otherwise 0 stroke = WHITE onMouseClicked = { Timeline(at (3 s) {radius -> 0}).play() 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); } } } 591 Characters content = circles new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } }); new Timeline { circle.setStroke(Color.WHITE); cycleCount = INDEFINITE circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) autoReverse = true .then(4) keyFrames = for (circle <- circles) yield at (40 s) { .otherwise(0)); Set( circles.add(circle); circle.centerX -> random * stage.width, } circle.centerY -> random * stage.height root.getChildren().addAll(circles); ) primaryStage.setScene(scene); } primaryStage.show(); }.play(); } Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 14
object VanishingCircles extends 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) } } } } 15
object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 class for JavaFX Base applications 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) } } } } 16
object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 Declarative Stage scene = new Scene { fill = BLACK definition 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) } } } } 17
object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Inline property height = 600 definitions 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) } } } } 18
object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Sequence Creation Via height = 600 Loop 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) } } } } 19
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" 20
Animation in Scala val timeline = 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(); 21
JavaFX Script-like animation Animation in Scala syntax: at (duration) {keyframes} val timeline = 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(); 22
Animation in Scala val timeline = 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(); Operator overloading for animation syntax 23
Animation in Scala val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width tween EASE_BOTH, circle.centerY -> random * stage.height tween EASE_IN ) } } timeline.play(); Optional tween syntax 24
Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects > 100% type-safe onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 25
Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects Optional event > 100% type-safe parameter {(event) => body} onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 26
Jumping Frogs Puzzle Image by renwest: http://www.flickr.com/photos/19941963@N00/438340463 27
Jumping Frogs Puzzle > My first ScalaFX program > Similar to (but more concise as) my version using JavaFX 1.2 > After a few JavaFX 1.2 to ScalaFX translation iterations it just worked > After some MVC rethinking and a few refactoring iterations it worked even better (e.g. it is possible to click on a jumping frog) 28
Application object JumpingFrogsPuzzle extends JFXApp { stage = new Stage { title = TITLE scene = new Scene { content = theShapes.canvasShape :: theShapes.stoneShapes ::: theView.frogShapes } } } 29
Frog trait Frog { def movesToRight: Boolean def movesToLeft: Boolean } class LeftFrog() extends Frog { def movesToRight = true def movesToLeft = false } class RightFrog() extends Frog { def movesToRight = false def movesToLeft = true } 30
Model (frogMap) var frogMap: Map[Int, Frog] = _ private val frogAtPosition = (i: Int) => frogMap(i) val positionOf = (frog: Frog) => (for { (i, `frog`) <- frogMap } yield i) head 31
Model (move) private val move = (next: Int => Int) => (frog: Frog) => frogMap = (for { entry@(_, aFrog) <- frogMap if (aFrog != frog) } yield { entry }) + (next(positionOf(frog)) -> frog) 32
View (jump) private val jump = (length: Int) => (direction: (Double, Double) => Double) => (frogShape: FrogShape) => { // ... Timeline(Seq( at(midTime) { frogShape.centerX -> midCenterX }, at(midTime) { frogShape.centerY -> midCenterY }, at(endTime) { frogShape.centerX -> endCenterX }, at(endTime) { frogShape.centerY -> endCenterY } )).play() } 33
View (control) private val control: Unit => Unit = { _ => view.frogShapes.foreach { frogShape => frogShape.onMouseClicked = { (_: MouseEvent) => val frog = frogShape.frog if (model.canMoveOneRight(frog)) { view.jumpOneRight(frogShape) model.moveOneRight(frog) } else if (model.canMoveTwoRight(frog)) { view.jumpTwoRight(frogShape) model.moveTwoRight(frog) 34
ScalaFX Internals a.k.a. How to Write Your Own Scala DSL With quotes from Stephen Colebourne (@jodastephen) to help us keep our sanity! Disclaimer: Statements taken from http://blog.joda.org and may not accurately reflect his opinion or viewpoint. 35
Application Initialization > JavaFX Requires all UI code executed on the Application Thread > But our ScalaFX Application has no start method: object VanishingCircles extends JFXApp { stage = new Stage { ... } } How Does This Code Work?!? 36
DelayedInit > Introduced in Scala 2.9 > How to Use It: 1. Extend a special trait called DelayedInit 2. Implement a method of type:  def delayedInit(x: => Unit): Unit 3. Store off the init closure and call it on the Application Thread Joda says... For me, Scala didn't throw enough away and added too much - a lethal combination. 37
Hierarchical Implicit Conversions > ScalaFX defines a set of proxies that mirror the JavaFX hierarchy > JavaFX classes are "implicitly" wrapped when you call a ScalaFX API > But Scala implicit priority ignores type hierarchy! JFXNode SFXNode JFXShape ? SFXShape JFXCircle ! SFXCircle 38
N-Level Implicit Precedence > Scala throws an exception if two implicits have the same precedence > Classes that are extended have 1 lower precedence: object HighPriorityIncludes extends LowerPriorityIncludes {...} trait LowerPriorityIncludes {...} > You can stack extended traits n-levels deep to reduce precision by n Joda says... Well, it may be type safe, but its also silent and very deadly. 39
Properties > JavaFX supports properties of type Boolean, Integer, Long, Float, Double, String, and Object > Properties use Generics for type safety > But generics don't support primitives... > JavaFX solves this with 20 interfaces and 44 classes for all the type/readable/writable combinations. > Can we do better? 40
@specialized > Special annotation that generates primitive variants of the class > Improves performance by avoiding boxing/unboxing trait ObservableValue[@specialized(Int, Long, Float, Double, Boolean) T, J] > Cuts down on code duplication (ScalaFX only has 18 property/value classes total) Joda says... Whatever the problem, the type system is bound to be part of the solution. 41
Bindings > How does Scala know what order to evaluate this in? text <== when (rect.hover || circle.hover && !disabled) then textField.text + " is enabled" otherwise "disabled And why the funky bind operator?!? 42
Operator Precedence Rules > First Character Determines Precedence Lowest Precedence 10. (all letters) Exception Assignment 9. | Operators, which are 8. ^ even lower... 7. & 6. < > 11. Assignment Operators 5. = ! end with equal 4. : > But don't start with equal 3. + * > And cannot be one of:  <= 2. / %  >= 1. (all other special  != characters) Highest Precedence 43
Operator Precedence text <== when (rect.hover || circle.hover 11 10 9 && !disabled) then textField.text + " is 7 5 10 3 enabled" otherwise "disabled" 10 Joda says... Personally, I find the goal of the open and flexible syntax (arbitrary DSLs) to be not worth the pain 44
Conclusion > You can use Scala and JavaFX together. > ScalaFX provides cleaner APIs that are tailor designed for Scala. > Try using ScalaFX today and help contribute APIs for our upcoming 1.0 release! http://code.google.com/p/scalafx/
Stephen Chin steveonjava@gmail.com tweet: @steveonjava Pro JavaFX 2 Platform Available Now! 46

More Related Content

Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
PPT
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
PPTX
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
Mary Had a Little λ (QCon)
PDF
Mary Had a Little λ (QCon)
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
PPTX
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - JavaOne 2011
PPTX
JavaFX 2.0 With Alternative Languages - JavaOne 2011
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
PDF
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
ScalaDays 2014 - Reactive Scala 3D Game Engine
PPTX
ScalaDays 2014 - Reactive Scala 3D Game Engine
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions
PPTX
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
Mary Had a Little λ (QCon)
Mary Had a Little λ (QCon)
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - JavaOne 2011
JavaFX 2.0 With Alternative Languages - JavaOne 2011
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions

What's hot

Java FX 2.0 - A Developer's Guide
PDF
Java FX 2.0 - A Developer's Guide
JavaFX and Scala in the Cloud
PPTX
JavaFX and Scala in the Cloud
The Ring programming language version 1.6 book - Part 46 of 189
PDF
The Ring programming language version 1.6 book - Part 46 of 189
Clojure Deep Dive
PDF
Clojure Deep Dive
Zend Framework 1 + Doctrine 2
PDF
Zend Framework 1 + Doctrine 2
Xm lparsers
PPT
Xm lparsers
Clojure: Functional Concurrency for the JVM (presented at OSCON)
PDF
Clojure: Functional Concurrency for the JVM (presented at OSCON)
The Ring programming language version 1.7 book - Part 57 of 196
PDF
The Ring programming language version 1.7 book - Part 57 of 196
Gazr
KEY
Gazr
Beyond Breakpoints: Advanced Debugging with XCode
PDF
Beyond Breakpoints: Advanced Debugging with XCode
PHP and MySQL Tips and tricks, DC 2007
PDF
PHP and MySQL Tips and tricks, DC 2007
The Ring programming language version 1.2 book - Part 35 of 84
PDF
The Ring programming language version 1.2 book - Part 35 of 84
Alternate JVM Languages
PDF
Alternate JVM Languages
The Ring programming language version 1.9 book - Part 53 of 210
PDF
The Ring programming language version 1.9 book - Part 53 of 210
Backbone.js: Run your Application Inside The Browser
PDF
Backbone.js: Run your Application Inside The Browser
SDC - Einführung in Scala
PPT
SDC - Einführung in Scala
The Ring programming language version 1.10 book - Part 47 of 212
PDF
The Ring programming language version 1.10 book - Part 47 of 212
The Ring programming language version 1.7 book - Part 33 of 196
PDF
The Ring programming language version 1.7 book - Part 33 of 196
Scala in practice
PDF
Scala in practice
The Ring programming language version 1.2 book - Part 79 of 84
PDF
The Ring programming language version 1.2 book - Part 79 of 84
Java FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's Guide
JavaFX and Scala in the Cloud
JavaFX and Scala in the Cloud
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
Clojure Deep Dive
Clojure Deep Dive
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2
Xm lparsers
Xm lparsers
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at OSCON)
The Ring programming language version 1.7 book - Part 57 of 196
The Ring programming language version 1.7 book - Part 57 of 196
Gazr
Gazr
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84
Alternate JVM Languages
Alternate JVM Languages
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
SDC - Einführung in Scala
SDC - Einführung in Scala
The Ring programming language version 1.10 book - Part 47 of 212
The Ring programming language version 1.10 book - Part 47 of 212
The Ring programming language version 1.7 book - Part 33 of 196
The Ring programming language version 1.7 book - Part 33 of 196
Scala in practice
Scala in practice
The Ring programming language version 1.2 book - Part 79 of 84
The Ring programming language version 1.2 book - Part 79 of 84

Viewers also liked

JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
PPTX
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
Pf con scala
PPTX
Pf con scala
Scala en la Practica
PPTX
Scala en la Practica
Introducción a Scala
PPTX
Introducción a Scala
Programación Funcional en Scala
PDF
Programación Funcional en Scala
Curso de Scala: Trabajando con variables
PDF
Curso de Scala: Trabajando con variables
Scala - just good for Java shops?
PDF
Scala - just good for Java shops?
Introducción a scala
PDF
Introducción a scala
Koreference
PDF
Koreference
Scala+swing
ODP
Scala+swing
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
PPTX
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Confessions of a Former Agile Methodologist (JFrog Edition)
PPTX
Confessions of a Former Agile Methodologist (JFrog Edition)
Oracle IoT Kids Workshop
PPTX
Oracle IoT Kids Workshop
Devoxx4Kids NAO Workshop
PPTX
Devoxx4Kids NAO Workshop
Devoxx4Kids Lego Workshop
PPTX
Devoxx4Kids Lego Workshop
4 Introducción al lenguaje Scala
PPTX
4 Introducción al lenguaje Scala
Scala
PPT
Scala
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
Pf con scala
Pf con scala
Scala en la Practica
Scala en la Practica
Introducción a Scala
Introducción a Scala
Programación Funcional en Scala
Programación Funcional en Scala
Curso de Scala: Trabajando con variables
Curso de Scala: Trabajando con variables
Scala - just good for Java shops?
Scala - just good for Java shops?
Introducción a scala
Introducción a scala
Koreference
Koreference
Scala+swing
Scala+swing
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Raspberry Pi Gaming 4 Kids (Devoxx4Kids)
Confessions of a Former Agile Methodologist (JFrog Edition)
Confessions of a Former Agile Methodologist (JFrog Edition)
Oracle IoT Kids Workshop
Oracle IoT Kids Workshop
Devoxx4Kids NAO Workshop
Devoxx4Kids NAO Workshop
Devoxx4Kids Lego Workshop
Devoxx4Kids Lego Workshop
4 Introducción al lenguaje Scala
4 Introducción al lenguaje Scala
Scala
Scala

Similar to JavaFX and Scala - Like Milk and Cookies

Raspberry Pi à la GroovyFX
PPTX
Raspberry Pi à la GroovyFX
Java Fx Tutorial01
KEY
Java Fx Tutorial01
Retro gaming with lambdas stephen chin
PPTX
Retro gaming with lambdas stephen chin
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
PPTX
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Javafx Overview 90minutes
PDF
Javafx Overview 90minutes
Javafx Overview 90minutes
PDF
Javafx Overview 90minutes
Javafx Overview 90minutes
PDF
Javafx Overview 90minutes
Groovy's Builder
PDF
Groovy's Builder
Sbaw091110
KEY
Sbaw091110
Sbaw091117
KEY
Sbaw091117
JavaFX and Scala in the Cloud: Stephen Chin
PDF
JavaFX and Scala in the Cloud: Stephen Chin
JavaFX 1.0 SDK Aquarium Paris
PDF
JavaFX 1.0 SDK Aquarium Paris
Artdm170 Week6 Scripting Motion
KEY
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
KEY
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
KEY
Artdm170 Week6 Scripting Motion
Artdm170 week6 scripting_motion
KEY
Artdm170 week6 scripting_motion
Artdm170 Week6 Scripting Motion
KEY
Artdm170 Week6 Scripting Motion
java_for_future_15-Multithreaded-Graphics.pptx
PPTX
java_for_future_15-Multithreaded-Graphics.pptx
Slides mihail-ivanchev-1
PDF
Slides mihail-ivanchev-1
ARTDM 170, Week 13: Text Elements + Arrays
KEY
ARTDM 170, Week 13: Text Elements + Arrays
Raspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFX
Java Fx Tutorial01
Java Fx Tutorial01
Retro gaming with lambdas stephen chin
Retro gaming with lambdas stephen chin
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Javafx Overview 90minutes
Javafx Overview 90minutes
Javafx Overview 90minutes
Javafx Overview 90minutes
Javafx Overview 90minutes
Javafx Overview 90minutes
Groovy's Builder
Groovy's Builder
Sbaw091110
Sbaw091110
Sbaw091117
Sbaw091117
JavaFX and Scala in the Cloud: Stephen Chin
JavaFX and Scala in the Cloud: Stephen Chin
JavaFX 1.0 SDK Aquarium Paris
JavaFX 1.0 SDK Aquarium Paris
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
Artdm170 week6 scripting_motion
Artdm170 week6 scripting_motion
Artdm170 Week6 Scripting Motion
Artdm170 Week6 Scripting Motion
java_for_future_15-Multithreaded-Graphics.pptx
java_for_future_15-Multithreaded-Graphics.pptx
Slides mihail-ivanchev-1
Slides mihail-ivanchev-1
ARTDM 170, Week 13: Text Elements + Arrays
ARTDM 170, Week 13: Text Elements + Arrays

More from Stephen Chin

DevOps Tools for Java Developers v2
PPTX
DevOps Tools for Java Developers v2
10 Ways Everyone Can Support the Java Community
PPTX
10 Ways Everyone Can Support the Java Community
Java Clients and JavaFX: The Definitive Guide
PPTX
Java Clients and JavaFX: The Definitive Guide
DevOps Tools for Java Developers
PPTX
DevOps Tools for Java Developers
Java Clients and JavaFX - Presented to LJC
PPTX
Java Clients and JavaFX - Presented to LJC
RetroPi Handheld Raspberry Pi Gaming Console
PPTX
RetroPi Handheld Raspberry Pi Gaming Console
JavaFX on Mobile (by Johan Vos)
PPTX
JavaFX on Mobile (by Johan Vos)
Raspberry Pi with Java (JJUG)
PPTX
Raspberry Pi with Java (JJUG)
Confessions of a Former Agile Methodologist
PPTX
Confessions of a Former Agile Methodologist
Internet of Things Magic Show
PPTX
Internet of Things Magic Show
Zombie Time - JSR 310 for the Undead
PPTX
Zombie Time - JSR 310 for the Undead
JCrete Embedded Java Workshop
PPTX
JCrete Embedded Java Workshop
OpenJFX on Android and Devices
PPTX
OpenJFX on Android and Devices
Java on Raspberry Pi Lab
PPTX
Java on Raspberry Pi Lab
Java 8 for Tablets, Pis, and Legos
PDF
Java 8 for Tablets, Pis, and Legos
DukeScript
PDF
DukeScript
Raspberry Pi Gaming 4 Kids - Dutch Version
PDF
Raspberry Pi Gaming 4 Kids - Dutch Version
Raspberry pi gaming 4 kids
PPTX
Raspberry pi gaming 4 kids
LUGOD Raspberry Pi Hacking
PPTX
LUGOD Raspberry Pi Hacking
Moving to the Client - JavaFX and HTML5
PPTX
Moving to the Client - JavaFX and HTML5
DevOps Tools for Java Developers v2
DevOps Tools for Java Developers v2
10 Ways Everyone Can Support the Java Community
10 Ways Everyone Can Support the Java Community
Java Clients and JavaFX: The Definitive Guide
Java Clients and JavaFX: The Definitive Guide
DevOps Tools for Java Developers
DevOps Tools for Java Developers
Java Clients and JavaFX - Presented to LJC
Java Clients and JavaFX - Presented to LJC
RetroPi Handheld Raspberry Pi Gaming Console
RetroPi Handheld Raspberry Pi Gaming Console
JavaFX on Mobile (by Johan Vos)
JavaFX on Mobile (by Johan Vos)
Raspberry Pi with Java (JJUG)
Raspberry Pi with Java (JJUG)
Confessions of a Former Agile Methodologist
Confessions of a Former Agile Methodologist
Internet of Things Magic Show
Internet of Things Magic Show
Zombie Time - JSR 310 for the Undead
Zombie Time - JSR 310 for the Undead
JCrete Embedded Java Workshop
JCrete Embedded Java Workshop
OpenJFX on Android and Devices
OpenJFX on Android and Devices
Java on Raspberry Pi Lab
Java on Raspberry Pi Lab
Java 8 for Tablets, Pis, and Legos
Java 8 for Tablets, Pis, and Legos
DukeScript
DukeScript
Raspberry Pi Gaming 4 Kids - Dutch Version
Raspberry Pi Gaming 4 Kids - Dutch Version
Raspberry pi gaming 4 kids
Raspberry pi gaming 4 kids
LUGOD Raspberry Pi Hacking
LUGOD Raspberry Pi Hacking
Moving to the Client - JavaFX and HTML5
Moving to the Client - JavaFX and HTML5

Recently uploaded

ZGC: A Decade of Innovation by Stefan Johansson
PDF
ZGC: A Decade of Innovation by Stefan Johansson
From Gatekeeper to Kyverno : Kubernetes Policy Management with Performance by...
PDF
From Gatekeeper to Kyverno : Kubernetes Policy Management with Performance by...
ChatGPT Ain't Got $%@& On Me! by Andy Pavlo
PDF
ChatGPT Ain't Got $%@& On Me! by Andy Pavlo
xCapture v3: Efficient, Always-On Thread Level Observability with eBPF by Tan...
PPTX
xCapture v3: Efficient, Always-On Thread Level Observability with eBPF by Tan...
Dragino商品カタログ 2025.7 LoRaWAN・NB-IoT・LTE-M(LTE Cat.M1)対応センサーリスト
PDF
Dragino商品カタログ 2025.7 LoRaWAN・NB-IoT・LTE-M(LTE Cat.M1)対応センサーリスト
Data Structure - 9 Recursion
PDF
Data Structure - 9 Recursion
The Tale of Taming TigerBeetle's Tail Latency by Tobias Ziegler
PDF
The Tale of Taming TigerBeetle's Tail Latency by Tobias Ziegler
NDP Act GAID Simplified: From Confusion to Compliance
PDF
NDP Act GAID Simplified: From Confusion to Compliance
Session 6 Specialized AI Associate Series: The GenAI Experience in UiPath Doc...
PPTX
Session 6 Specialized AI Associate Series: The GenAI Experience in UiPath Doc...
Milvus Community Meetup SF (Oct 21, 2025)
PDF
Milvus Community Meetup SF (Oct 21, 2025)
"The Art of Web Scraping: Tree Algorithms and JS Magic", Dmytro Tarasenko
PPTX
"The Art of Web Scraping: Tree Algorithms and JS Magic", Dmytro Tarasenko
Session 3 - UiPath Coded Agents & MCP Server in Action
PDF
Session 3 - UiPath Coded Agents & MCP Server in Action
CymruSec 2025 - Wales' Inaugural Cyber Summit
PDF
CymruSec 2025 - Wales' Inaugural Cyber Summit
Enterprise Architecture for Microsoft 365: From Vision to Value
PPTX
Enterprise Architecture for Microsoft 365: From Vision to Value
Airtable Building Semantic Search with Milvus
PDF
Airtable Building Semantic Search with Milvus
Keynote: X-rAI Specs, Submarines and Juice
PDF
Keynote: X-rAI Specs, Submarines and Juice
Session 5 - Specialized AI Associate Series: Build a Document Understanding ...
PPTX
Session 5 - Specialized AI Associate Series: Build a Document Understanding ...
Design Considerations for P99-optimized Hash Tables by Steve Heller
PDF
Design Considerations for P99-optimized Hash Tables by Steve Heller
Top-10-Cloud-Service-Companies-in-2025-Market-Leaders-and-Innovators.pdf
PDF
Top-10-Cloud-Service-Companies-in-2025-Market-Leaders-and-Innovators.pdf
ClipsField AI - Transform Static Images Into Cinematic Videos in Minutes.pdf
PDF
ClipsField AI - Transform Static Images Into Cinematic Videos in Minutes.pdf
ZGC: A Decade of Innovation by Stefan Johansson
ZGC: A Decade of Innovation by Stefan Johansson
From Gatekeeper to Kyverno : Kubernetes Policy Management with Performance by...
From Gatekeeper to Kyverno : Kubernetes Policy Management with Performance by...
ChatGPT Ain't Got $%@& On Me! by Andy Pavlo
ChatGPT Ain't Got $%@& On Me! by Andy Pavlo
xCapture v3: Efficient, Always-On Thread Level Observability with eBPF by Tan...
xCapture v3: Efficient, Always-On Thread Level Observability with eBPF by Tan...
Dragino商品カタログ 2025.7 LoRaWAN・NB-IoT・LTE-M(LTE Cat.M1)対応センサーリスト
Dragino商品カタログ 2025.7 LoRaWAN・NB-IoT・LTE-M(LTE Cat.M1)対応センサーリスト
Data Structure - 9 Recursion
Data Structure - 9 Recursion
The Tale of Taming TigerBeetle's Tail Latency by Tobias Ziegler
The Tale of Taming TigerBeetle's Tail Latency by Tobias Ziegler
NDP Act GAID Simplified: From Confusion to Compliance
NDP Act GAID Simplified: From Confusion to Compliance
Session 6 Specialized AI Associate Series: The GenAI Experience in UiPath Doc...
Session 6 Specialized AI Associate Series: The GenAI Experience in UiPath Doc...
Milvus Community Meetup SF (Oct 21, 2025)
Milvus Community Meetup SF (Oct 21, 2025)
"The Art of Web Scraping: Tree Algorithms and JS Magic", Dmytro Tarasenko
"The Art of Web Scraping: Tree Algorithms and JS Magic", Dmytro Tarasenko
Session 3 - UiPath Coded Agents & MCP Server in Action
Session 3 - UiPath Coded Agents & MCP Server in Action
CymruSec 2025 - Wales' Inaugural Cyber Summit
CymruSec 2025 - Wales' Inaugural Cyber Summit
Enterprise Architecture for Microsoft 365: From Vision to Value
Enterprise Architecture for Microsoft 365: From Vision to Value
Airtable Building Semantic Search with Milvus
Airtable Building Semantic Search with Milvus
Keynote: X-rAI Specs, Submarines and Juice
Keynote: X-rAI Specs, Submarines and Juice
Session 5 - Specialized AI Associate Series: Build a Document Understanding ...
Session 5 - Specialized AI Associate Series: Build a Document Understanding ...
Design Considerations for P99-optimized Hash Tables by Steve Heller
Design Considerations for P99-optimized Hash Tables by Steve Heller
Top-10-Cloud-Service-Companies-in-2025-Market-Leaders-and-Innovators.pdf
Top-10-Cloud-Service-Companies-in-2025-Market-Leaders-and-Innovators.pdf
ClipsField AI - Transform Static Images Into Cinematic Videos in Minutes.pdf
ClipsField AI - Transform Static Images Into Cinematic Videos in Minutes.pdf

JavaFX and Scala - Like Milk and Cookies

  • 1.
    JavaFX and Scala – Like Milk and Cookies Stephen Chin Luc Duponcheel JavaFX Evangelist, Oracle Independent, ImagineJ steveonjava@gmail.com luc.duponcheel@gmail.com tweet: @steveonjava tweet: @LucDup
  • 2.
    Meet the Presenters Stephen Chin Luc Duponcheel Family Man Motorcyclist BeJUG Researcher
  • 3.
    JavaFX 2.0 Platform Immersive Application Experience > Cross-platform Animation, Video, Charting > Integrate Java, JavaScript, and HTML5 in the same application > New graphics stack takes advantage of hardware acceleration for 2D and 3D applications > Use your favorite IDE: NetBeans, Eclipse, IntelliJ, etc.
  • 4.
  • 5.
  • 6.
    JavaFX in Java > JavaFX API uses an enhanced JavaBeans pattern > Similar in feel to other UI toolkits (Swing, Pivot, etc.) > Uses builder pattern to minimize boilerplate
  • 7.
  • 8.
    Application Skeleton public class VanishingCircles extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Vanishing Circles"); Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); [create the circles...] root.getChildren().addAll(circles); primaryStage.setScene(scene); primaryStage.show(); [begin the animation...] } }
  • 9.
    Create the Circles List<Circle> circles = new ArrayList<Circle>(); for (int i = 0; i < 50; i++) { final Circle circle = new Circle(150); circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); circle.setStroke(Color.WHITE); [setup binding...] [setup event listeners...] circles.add(circle); } 9
  • 10.
    Setup Binding circle.strokeWidthProperty().bind(Bindings .when(circle.hoverProperty()) .then(4) .otherwise(0) ); 10
  • 11.
    Setup Event Listeners circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } }); 11
  • 12.
    Begin the Animation Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); 12
  • 13.
  • 14.
    Java vs. Scala DSL public class VanishingCircles extends Application { object VanishingCircles extends JFXApp { var circles: Seq[Circle] = null public static void main(String[] args) { stage = new Stage { Application.launch(args); title = "Vanishing Circles" } width = 800 height = 600 @Override scene = new Scene { public void start(Stage primaryStage) { fill = BLACK primaryStage.setTitle("Vanishing Circles"); circles = for (i <- 0 until 50) yield new Circle { Group root = new Group(); centerX = random * 800 Scene scene = new Scene(root, 800, 600, Color.BLACK); centerY = random * 600 List<Circle> circles = new ArrayList<Circle>(); radius = 150 for (int i = 0; i < 50; i++) { fill = color(random, random, random, .2) final Circle circle = new Circle(150); effect = new BoxBlur(10, 10, 3) 40 Lines circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(), Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); 33 Lines strokeWidth <== when (hover) then 4 otherwise 0 stroke = WHITE onMouseClicked = { Timeline(at (3 s) {radius -> 0}).play() 1299 Characters circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); } } } 591 Characters content = circles new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } } }); new Timeline { circle.setStroke(Color.WHITE); cycleCount = INDEFINITE circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) autoReverse = true .then(4) keyFrames = for (circle <- circles) yield at (40 s) { .otherwise(0)); Set( circles.add(circle); circle.centerX -> random * stage.width, } circle.centerY -> random * stage.height root.getChildren().addAll(circles); ) primaryStage.setScene(scene); } primaryStage.show(); }.play(); } Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() * 800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() * 600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX, moveY)); } moveCircles.play(); } } 14
  • 15.
    object VanishingCircles extends 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) } } } } 15
  • 16.
    object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 class for JavaFX Base applications 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) } } } } 16
  • 17.
    object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 height = 600 Declarative Stage scene = new Scene { fill = BLACK definition 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) } } } } 17
  • 18.
    object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Inline property height = 600 definitions 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) } } } } 18
  • 19.
    object VanishingCircles extends JFXApp { stage = new Stage { title = "Disappearing Circles" width = 800 Sequence Creation Via height = 600 Loop 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) } } } } 19
  • 20.
    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" 20
  • 21.
    Animation in Scala val timeline = 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(); 21
  • 22.
    JavaFX Script-like animation Animation in Scala syntax: at (duration) {keyframes} val timeline = 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(); 22
  • 23.
    Animation in Scala val timeline = 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(); Operator overloading for animation syntax 23
  • 24.
    Animation in Scala val timeline = new Timeline { cycleCount = INDEFINITE autoReverse = true keyFrames = for (circle <- circles) yield at (40 s) { Set( circle.centerX -> random * stage.width tween EASE_BOTH, circle.centerY -> random * stage.height tween EASE_IN ) } } timeline.play(); Optional tween syntax 24
  • 25.
    Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects > 100% type-safe onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 25
  • 26.
    Event Listeners in Scala > Supported using the built-in Closure syntax > Arguments for event objects Optional event > 100% type-safe parameter {(event) => body} onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius->0}).play() } 26
  • 27.
    Jumping Frogs Puzzle Image by renwest: http://www.flickr.com/photos/19941963@N00/438340463 27
  • 28.
    Jumping Frogs Puzzle > My first ScalaFX program > Similar to (but more concise as) my version using JavaFX 1.2 > After a few JavaFX 1.2 to ScalaFX translation iterations it just worked > After some MVC rethinking and a few refactoring iterations it worked even better (e.g. it is possible to click on a jumping frog) 28
  • 29.
    Application object JumpingFrogsPuzzle extends JFXApp { stage = new Stage { title = TITLE scene = new Scene { content = theShapes.canvasShape :: theShapes.stoneShapes ::: theView.frogShapes } } } 29
  • 30.
    Frog trait Frog { def movesToRight: Boolean def movesToLeft: Boolean } class LeftFrog() extends Frog { def movesToRight = true def movesToLeft = false } class RightFrog() extends Frog { def movesToRight = false def movesToLeft = true } 30
  • 31.
    Model (frogMap) var frogMap: Map[Int, Frog] = _ private val frogAtPosition = (i: Int) => frogMap(i) val positionOf = (frog: Frog) => (for { (i, `frog`) <- frogMap } yield i) head 31
  • 32.
    Model (move) private val move = (next: Int => Int) => (frog: Frog) => frogMap = (for { entry@(_, aFrog) <- frogMap if (aFrog != frog) } yield { entry }) + (next(positionOf(frog)) -> frog) 32
  • 33.
    View (jump) private val jump = (length: Int) => (direction: (Double, Double) => Double) => (frogShape: FrogShape) => { // ... Timeline(Seq( at(midTime) { frogShape.centerX -> midCenterX }, at(midTime) { frogShape.centerY -> midCenterY }, at(endTime) { frogShape.centerX -> endCenterX }, at(endTime) { frogShape.centerY -> endCenterY } )).play() } 33
  • 34.
    View (control) private val control: Unit => Unit = { _ => view.frogShapes.foreach { frogShape => frogShape.onMouseClicked = { (_: MouseEvent) => val frog = frogShape.frog if (model.canMoveOneRight(frog)) { view.jumpOneRight(frogShape) model.moveOneRight(frog) } else if (model.canMoveTwoRight(frog)) { view.jumpTwoRight(frogShape) model.moveTwoRight(frog) 34
  • 35.
    ScalaFX Internals a.k.a. How to Write Your Own Scala DSL With quotes from Stephen Colebourne (@jodastephen) to help us keep our sanity! Disclaimer: Statements taken from http://blog.joda.org and may not accurately reflect his opinion or viewpoint. 35
  • 36.
    Application Initialization > JavaFX Requires all UI code executed on the Application Thread > But our ScalaFX Application has no start method: object VanishingCircles extends JFXApp { stage = new Stage { ... } } How Does This Code Work?!? 36
  • 37.
    DelayedInit > Introduced in Scala 2.9 > How to Use It: 1. Extend a special trait called DelayedInit 2. Implement a method of type:  def delayedInit(x: => Unit): Unit 3. Store off the init closure and call it on the Application Thread Joda says... For me, Scala didn't throw enough away and added too much - a lethal combination. 37
  • 38.
    Hierarchical Implicit Conversions > ScalaFX defines a set of proxies that mirror the JavaFX hierarchy > JavaFX classes are "implicitly" wrapped when you call a ScalaFX API > But Scala implicit priority ignores type hierarchy! JFXNode SFXNode JFXShape ? SFXShape JFXCircle ! SFXCircle 38
  • 39.
    N-Level Implicit Precedence > Scala throws an exception if two implicits have the same precedence > Classes that are extended have 1 lower precedence: object HighPriorityIncludes extends LowerPriorityIncludes {...} trait LowerPriorityIncludes {...} > You can stack extended traits n-levels deep to reduce precision by n Joda says... Well, it may be type safe, but its also silent and very deadly. 39
  • 40.
    Properties > JavaFX supports properties of type Boolean, Integer, Long, Float, Double, String, and Object > Properties use Generics for type safety > But generics don't support primitives... > JavaFX solves this with 20 interfaces and 44 classes for all the type/readable/writable combinations. > Can we do better? 40
  • 41.
    @specialized > Special annotation that generates primitive variants of the class > Improves performance by avoiding boxing/unboxing trait ObservableValue[@specialized(Int, Long, Float, Double, Boolean) T, J] > Cuts down on code duplication (ScalaFX only has 18 property/value classes total) Joda says... Whatever the problem, the type system is bound to be part of the solution. 41
  • 42.
    Bindings > How does Scala know what order to evaluate this in? text <== when (rect.hover || circle.hover && !disabled) then textField.text + " is enabled" otherwise "disabled And why the funky bind operator?!? 42
  • 43.
    Operator Precedence Rules > First Character Determines Precedence Lowest Precedence 10. (all letters) Exception Assignment 9. | Operators, which are 8. ^ even lower... 7. & 6. < > 11. Assignment Operators 5. = ! end with equal 4. : > But don't start with equal 3. + * > And cannot be one of:  <= 2. / %  >= 1. (all other special  != characters) Highest Precedence 43
  • 44.
    Operator Precedence text <== when (rect.hover || circle.hover 11 10 9 && !disabled) then textField.text + " is 7 5 10 3 enabled" otherwise "disabled" 10 Joda says... Personally, I find the goal of the open and flexible syntax (arbitrary DSLs) to be not worth the pain 44
  • 45.
    Conclusion > You can use Scala and JavaFX together. > ScalaFX provides cleaner APIs that are tailor designed for Scala. > Try using ScalaFX today and help contribute APIs for our upcoming 1.0 release! http://code.google.com/p/scalafx/
  • 46.
    Stephen Chin steveonjava@gmail.com tweet: @steveonjava Pro JavaFX 2 Platform Available Now! 46

Editor's Notes

AltStyle によって変換されたページ (->オリジナル) /