"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
Java FX 2.0 - A Developer's Guide
1. JavaFX 2.0 – A Java Developer's Guide
Stephen Chin
Chief Agile Methodologist, GXS
http://steveonjava.com @steveonjava
Peter Pilgrim
Oracle Java Champion
http://www.xenonique.co.uk/blog/ @peter_pilgrim
2. Meet the Presenters
Stephen Chin Peter Pilgrim
@steveonjava @peter_pilgrim
Football, Music &
Partner
Family Man
Motorcyclist
3. This is a Participatory Session!
> Every now and then we will say something
interesting… and it will go out in a tweet.
> Follow @steveonjava to watch the tweets and
retweet the ones you like to your followers
> Feel free to create your own tweets using the
hash tags "#JavaFX #Devoxx"
> We have some goodies for folks who play. J
3
4. At the end of the day, on the one
hand we have computer systems,
and on the other, people.
Connecting them together, and
allowing people to interact with
computer systems in a compelling
way, requires graphical user
interfaces
Chris Oliver, Creator of F3
http://blogs.oracle.com/chrisoliver/entry/epitaph
4
5. JavaFX 2.0 Platform
Immersive Desktop Experience
Combining the Best of JavaFX and Web
Technologies
> Leverage your Java skills with modern
JavaFX APIs
> Integrate Java, JavaScript, and HTML5 in
the same application
> New graphics stack takes advantage of
hardware acceleration for 2D and 3D
applications
> Integrate in Swing applications using
JFXPanel
> User your favorite IDE: NetBeans,
Eclipse, IntelliJ, etc.
7. Headline News
> RT @Stephan007: The #JavaOne11 channel
on #Parleys passed 51.800 views! Most
viewed: "Introduction to #JavaFX 2.0", close to
11,000 - @JavaFX4You, 9th November 2011
> The most interesting announcement came
when Oracle demoed both Java and JavaFX
applications running on a Windows tablet, an
iPad, and a "Linux-based tablet". - Eric Bruno,
Dr Dobbs Journal, 5th October 2011
7
8. Platform Support
> Windows fully supported
l For 3D you need one of the supported graphics
cards (ATI, NVidia, Intel)
> Mac OS X preview available
> Linux Planned for end of 2012
8
9. Windows OS Requirements
Operating System (32-Bit and 64-Bit) Browsers (32-Bit and 64-Bit)
Windows XP Home and Professional Internet Explorer 7 and 8
with Service Pack 3 Chrome
Windows Vista Home Basic, Home Internet Explorer 7, 8, and 9
Premium, Business, and Ultimate with Firefox 3.5, 3.6, and 4
Service Pack 2 Chrome
Windows 7 Home Premium, Internet Explorer 8 and 9
Professional, and Ultimate Firefox 3.5, 3.6, and 4
Chrome
9
10. Supported Graphics Cards
Supported Graphics Processing
Graphics Card Units (GPUs)
NVIDIA Mobile GPUs: GeForce 8M and 100M
series or higher, NVS 2100M series or
higher, and Mobility Quadro FX 300M
series or higher
Desktop GPUs: GeForce 8 and 100
series or higher
Workstation GPUs: Quadro FX 300
series or higher
ATI Mobile GPUs: Mobility Radeon HD
3000, 4000, and 5000 series
Desktop GPUs: Radeon HD 2400,
3000, 4000, 5000, and 6000 series
Intel Mobile GPUs: GMA 4500MHD and
GMA HD
Desktop GPUs: GMA 4500 and GMA
HD
10
11. Building JavaFX Applications
> Deploys in the browser or on desktop
> Pure Java APIs
> Includes builders for declarative construction
> Alternative languages can also be used for
simpler UI creation
l GroovyFX
l ScalaFX
l Visage
11
12. Hello Devoxx (Java Version)
public
class
HelloDevoxx
extends
Application
{
public
static
void
main(String[]
args)
{
launch(args);
}
@Override
public
void
start(Stage
primaryStage)
{
primaryStage.setTitle("Hello
Devoxx");
Group
root
=
new
Group();
19 Lines
Scene
scene
=
new
Scene(root,
400,
250,
Color.ALICEBLUE);
Text
text
=
new
Text();
Characters
425
text.setX(105);
text.setY(120);
text.setFont(new
Font(30));
text.setText("Hello
Devoxx");
root.getChildren().add(text);
primaryStage.setScene(scene);
primaryStage.show();
}
}
12
15. Hello Devoxx (ScalaFX Version)
object
HelloDevoxx
extends
JFXApp
{
stage
=
new
Stage
{
title
=
"Hello
Devoxx"
width
=
400
height
=
250
scene
=
new
Scene
{
fill
=
BLUE
Lines
16
Text
{
163 Characters
x
=
105
y
=
120
text
=
"Hello
Devoxx"
font
=
Font(size:
30)
}
}
}
}
15
19. JavaFX 2.0 Properties
> Primitive Properties
> Object Properties
> FX List Collection Properties
> Properties are:
l Observable
l Lazy
l Type Safe
19
20. Properties in Java
Property Declaration
public
class
Person
{
private
StringProperty
firstName;
public
void
setFirstName(String
val)
{
firstNameProperty().set(val);
}
public
String
getFirstName()
{
return
firstNameProperty().get();
}
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName");
return
firstName;
}
}
20
21. Properties in Java
public
class
Person
{
private
StringProperty
firstName;
public
void
setFirstName(String
val)
{
firstNameProperty().set(val);
}
public
String
getFirstName()
{
return
firstNameProperty().get();
Setter Method
}
(Convenience)
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName");
return
firstName;
}
}
21
22. Properties in Java
public
class
Person
{
private
StringProperty
firstName;
Getter Method
public
void
setFirstName(String
val)
{
(Convenience)
firstNameProperty().set(val);
}
public
String
getFirstName()
{
return
firstNameProperty().get();
}
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName");
return
firstName;
}
}
22
23. Properties in Java
public
class
Person
{
private
StringProperty
firstName;
public
void
setFirstName(String
val)
{
Property Fetcher
firstNameProperty().set(val);
(Lazy Construction)
}
public
String
getFirstName()
{
return
firstNameProperty().get();
}
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName");
return
firstName;
}
}
23
24. Properties in Java
public
class
Person
{
private
StringProperty
firstName;
Even Lazier…
public
void
setFirstName(String
val)
{
firstNameProperty().set(val);
}
public
String
getFirstName()
{
return
firstName
==
null
?
null
:
firstNameProperty().get();
}
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName");
return
firstName;
}
}
24
25. Properties in Java
public
class
Person
{
private
StringProperty
firstName;
public
void
setFirstName(String
val)
{
With initial value
firstNameProperty().set(val);
}
public
String
getFirstName()
{
return
firstName
==
null
?
"Peter"
:
firstNameProperty().get();
}
public
StringProperty
firstNameProperty()
{
if
(firstName
==
null)
firstName
=
new
SimpleStringProperty(this,
"firstName",
"Peter");
return
firstName;
}
}
25
26. Demo
Properties
Undirectional, Bidirectional and
Lazy binding in Java
27. Listeners
> Change Listener
l Observable, old value, new value
> Invalidation Listeners
l Observable
2
7
28. Property Listener Example
IntegerProperty
temperature
=
new
SimpleIntegerProperty(0);
temperature.setOnChangeListener(
new
ChangeListener<Number>()
{
public
void
change(
ObservableValue<?
Extends
Number>
ov,
Number
newValue,
Number
oldValue)
System.out.printf(“%f
%f
%f”,
ov.doubleValue(),
oldValue.doubleValue(),
newValue.doubleValue()
}
);
temperature.set(2);
temperature.set(4);
28
29. Hey Ho! This is all just to say:
var
temperature:
Integer
=
23
on
replace
oldValue
{
println("temperature={temperature},
oldValue={oldValue}");
}
//
Visage
(previously
JavaFX
Script)
29
30. JavaFX 2.0 Observable Lists
> Extends java.util.List
> Includes addListener/removeListener
> For bulk operations use:
l addAll
l removeAll
l setAll
> Sort with
l FXCollections.sort()
30
31. List Change Listener
list.addListener(new
ListChangeListener<Item>()
{
public
void
onChanged(Change<Item>
c)
{
while
(c.next())
{
if
(c.wasPermutated())
{
for
(int
i
=
c.getFrom();
i
<
c.getTo();
i++)
{
int
newLoc
=
getPermutation(i);
//
handle
move
(a.k.a.
sort)
}
}
else
{
for
(Item
removed
:
c.getRemoved())
{
//
handle
removal
}
for
(Item
added
:
c.getAddedSubList())
{
//
handle
addition
}
}}}});
31
32. JavaFX 2.0 Observable Maps
> Extends java.util.Map
> Includes addListener() / removeListener()
> MapChangeListener
l Supports add()
/ remove()
l Can get associated:
l Key
l Old Value
l New Value
32
33. Binding in JavaFX 2.0
> One of the most important features of JavaFX 1.3
and prior
> Now supported via an API (that works with
Observable Properties)
> Can handle most cases quite elegantly and with
full type safety
33
38. Media View
1
Media View
2 Media Player Media
Media View
3
Media View
4
38
39. Breaking Glass
1. Divide a bounded area into four triangles
2. Are we there yet?
3. For each triangle
A. Choose a random side and split it to two
rectangles
B. Recursive descend the two triangles (step 2)
3
9
41. Button Control
> Simple Button Control
> Add and remove click event handler
> Support Cascading Style Sheets
41
42. Button Code
public
class
ButtonDemo
extends
AbstractDevoxxApplication
{
public
void
initialiseScene(Group
root)
{
VBox
vbox
=
VBoxBuilder.create().
spacing(25).layoutX(25).layoutY(25).build();
root.getChildren().add(vbox);
Button
red
=
ButtonBuilder.create()
.text("Red").style("-‐fx-‐base:
red;").build();
Button
yellow
=
ButtonBuilder.create()
.text("Yellow").style("-‐fx-‐base:
blue;")
.build();
Button
green
=
ButtonBuilder.create()
.text("Green").style("-‐fx-‐base:
green;")
.build();
vbox.getChildren().addAll(red,yellow,green);
}
/*
…
*/
}
42
43. TextField Control
> One line entry text field control
> Set OnAction event handler
> Can listen to individual key events
> Support Cascading Style Sheets
43
44. TextField Demo
public
class
TextDemo
extends
AbstractDevoxxApplication
{
public
void
initialiseScene(Group
root)
{
VBox
vbox
=
VBoxBuilder.create().spacing(25)
.layoutX(25).layoutY(25).build();
root.getChildren().add(vbox);
TextField
red
=
TextFieldBuilder.create()
.text("Red
Devoxx")
.style("-‐fx-‐base:
red;
-‐fx-‐font-‐size:
48pt;
")
.build();
TextField
green
=
TextFieldBuilder.create()
.text("Green
Devoxx")
.style("-‐fx-‐base:
green;
-‐fx-‐font-‐size:
24pt;
")
.build();
vbox.getChildren().addAll(red,green);
}
/*….
*/
}
44
45. ListView Control
> Displays a list of items
> Reuses cells for performance
> Default cell renderer can
display Strings
> For other object types
l Create custom CellFactory
45
47. TreeView Control
> Displays a tree view of items
> Can dynamically populate as
tree is expanded
> Default cell renderer can
display Strings
> For other object types
l Create custom CellFactory
47
48. TreeView Code
public
void
initialiseScene(Group
root)
{
/*…*/
TreeView
treeView
=
TreeViewBuilder.<String>create().root(
TreeItemBuilder.<String>create().value("JVM
Languages").children(
TreeItemBuilder.<String>create().value("Static").children(
new
TreeItem<String>("Scala"),
new
TreeItem<String>("Java"),
new
TreeItem<String>("Visage"),
/*…*/
).build(),
TreeItemBuilder.<String>create().value("Dynamic").children(
new
TreeItem<String>("Clojure"),
new
TreeItem<String>("Groovy"),
/*…*/
).build(),
/*…*/
).build()
).build();
/*…*/
}
48
49. ToolBar Demo
> Toolbar displays items horizontally or vertically
> Handles arbitrary number of items
> Can add any node to the toolbar, including
custom nodes
> Automatic adds an overflow hint if cannot display
all toolbar items
49
50. Toolbar Code
public
class
ToolBarDemo
extends
AbstractDevoxxApplication
{
public
void
initialiseScene(Group
root)
{
/*…*/
ToggleGroup
amFm
=
new
ToggleGroup();
ToolBar
toolBar
=
ToolBarBuilder.create().items(
new
Label("Volume"),
new
Slider(),
new
ToggleButton("Loudness"),
RadioButtonBuilder.create()
.text("AM").toggleGroup(amFm).build(),
RadioButtonBuilder.create()
.text("FM").toggleGroup(amFm).build(),
new
Button("Tune")
).build();
vbox.getChildren().addAll(toolBar);
}}
50
51. Progress Bars and Indicators
> Progress Bars can be laid out
vertically and horizontally
> Progress Indicator is a circular
widget
> Progress Bar and Indicator can be
indefinite
> Double property 0.0 <= x <= 1.0
51
53. Accordion Control
> Accordion is a space saving
components
> Accordian accept only
TitledPanes
> Each TitledPane managed
one scenegraph node
> Can choose the titled pane
expanded by default
53
54. Accordion Code
String
imageUrl
=
new
Image(ResizableImageViewDemo.class.
getResource("images/Squirrel.jpg").toExternalForm();
Accordion
accordion
=
AccordionBuilder.create().panes(
new
TitledPane("Button",
new
Button("Regular")),
new
TitledPane("ToggleButton",
new
ToggleButton("Toggle")),
imagePane
=
new
TitledPane("SquirrelImage",
ImageViewBuilder.create().image(imageUrl,
500,
500,
true,
true,
false)
).build()
)
).build()
54
55. TabPane Control
> Alternative space saving component
> Choose a side for the Tab
> Each manages one component node
> Tab pane has two modes:
l floating
l recessed
55
61. Group based
> Particularly using the JavaFX primitive nodes
under javafx.scene.shape.*;
> Design is not meant to be resized
> Layout is fixed at construction / initialisation time
6
1
62. Region based
> Region is the sub class of javafx.scene.Parent
> Adds the ability to resize a node, layout a
particular set of children
6
2
63. Control based
> Allows particular subclass of Region that permits
skinning of node with a stylesheet
> You need 3 classes
l The Control
java.scene.control.Control
l The Skinnable
java.scene.control.Skinnable
l The Behaviour
com.sun.javafx.scene.control.BehaviorBase
6
3
64. Control based contd
> See JFXtras.org for more examples of skinnable
components written for JavaFX 2.0
> Define CSS file referencing a Skin class
> A Skin is a Region (JavaFX 2.0)
com.sun.javafx.scene.control.BehaviorBase
com.sun.javafx.scene.control.SkinBase
6
4
65. Skins are StackPanes
> SkinBase is a type of StackPane
> A StackPane is a Region
> Idea of shuffling a deck of cards and only showing
one
6
5
66. Layout Children Method
void
layoutChildren()
> Layout all of the children of a Region based
component
> Compute the preferred width and height of the
children (first)
> May cache those values internally as part of the
component or use Constraints
6
6
67. Layout Boundaries
> SDK will make a request to find the best width and
height for your component.
> Your component must do the same for its children
> Implement at least computePrefWidth and
computePrefHeight methods!
6
7
72. Event Input on Node
> Mouse Events fall under the pointer iteraction
(single)
l Clicked, Entered, Exited, Pressed, Dragged,
Released, Wheel
l Target Entered, Target Exited
> Key Events
l Clicked, Pressed, Released
73. Event Input on Node
> It is possible to consume an event and stop it
bubbling further down the scene-graph hierarchy
> You can block a component from event interaction
> Using clever tricks (opaque shape) you can
implement dialog / focus / modal behaviour
86. Tips
> When Dragging a Node prefer to translate (X,Y)
> When Laying Out a Node prefer to set the position
with layoutX, layoutY
> Given steady state conditions you can swap
layout (X,Y) for translation (X,Y)
87. Tips 2
> Use blocking boolean flags to prevent conflict
when you animating children in a container
> If you are unsure about MT concurrency you can
always use AtomicBoolean
> Prefer JavaFX Properties
89. Displaying HTML in JavaFX
public
class
WebViewDemo
extends
Application
{
public
static
void
main(String[]
args)
{
launch(args);
}
@Override
public
void
start(Stage
stage)
{
WebView
webView
=
new
WebView();
webView.getEngine().load("http://
devoxx.com");
Scene
scene
=
new
Scene(webView);
stage.setScene(scene);
stage.setTitle("Web
View
Demo");
stage.show();
}}
89
90. For more info on Web/HTML5…
Moving to the Client –
JavaFX and HTML5
Stephen Chin
Kevin Nilson
Thursday 10:50 AM, Room 7
10 / 10 Break
90
92. Features of Groovy
> Modern language
l Closures
l AST Transforms
l Strongly typed dynamic language
> Tight integration with Java
l Very easy to port from Java to Groovy
> Declarative syntax with GroovyFX Builders
l Familiar to Groovy and JavaFX Script developers
93. Java vs. GroovyFX DSL
public
class
HelloStage
extends
Application
{
GroovyFX.start
{
stage
-‐>
def
sg
=
new
SceneGraphBuilder(stage)
public
void
start(Stage
stage)
{
stage.setTitle("Hello
Stage");
sg.stage(title:
“Hello
Stage”,
width:
600,
stage.setWidth(600);
height:
450)
{
stage.setHeight(450);
scene(fill:
groovyblue)
{
Scene
scene
=
new
Scene();
rectangle(x:
25,
y:
40,
width:
100,
scene.setFill(Color.LIGHTGREEN);
height:
50,
fill:
red)
21 Lines
Rectangle
rect
=
new
Rectangle();
rect.setX(25);
8 Lines
}
}
430 Characters
rect.setY(40);
rect.setWidth(100);
rect.setHeight(50);
}
180 Characters
rect.setFill(Color.RED);
scene.setRoot(new
Group(rect));
stage.setScene(scene);
stage.show();
}
public
static
void
main(String[]
args)
{
launch(HelloStage.class,
args);
}
}
93
102. Properties in GroovyFX
public class Person {!
@FXBindable String firstName; !
@FXBindable String lastName = “Smith”;!
}!
Optional initializers
102
103. Properties in GroovyFX
public class Person {!
@FXBindable String firstName; !
@FXBindable String lastName = “Smith”;!
}!
!
def p = new Person()!
def last = p.lastName! Get and set values
p.firstName = “Agent”!
!
103
104. Properties in GroovyFX
public class Person {!
@FXBindable String firstName; !
@FXBindable String lastName = “Smith”;!
}!
!
def p = new Person()!
def last = p.lastName! Access underlying
p.firstName = “Agent”! property for binding
!
textField(text: bind(p.lastNameProperty()))!
!
104
105. 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)
}
}
105
106. Animation in GroovyFX
timeline(cycleCount:
Timeline.INDEFINITE,
autoReverse:
true)
{
at
(1000.ms)
{
change(rect1,
'x')
to
200
tween
ease_both
change
rect2.yProperty()
to
200
tween
linear
}
}.play()
106
107. Animation in GroovyFX
timeline(cycleCount:
Timeline.INDEFINITE,
autoReverse:
true)
{
at
(1000.ms)
{
change(rect1,
'x')
to
200
tween
ease_both
change
rect2.yProperty()
to
200
tween
linear
}
}.play()
Easy animation syntax:
at (duration) {keyframes}
107
108. Animation in GroovyFX
timeline(cycleCount:
Timeline.INDEFINITE,
autoReverse:
true)
{
at
(1000.ms)
{
change(rect1,
'x')
to
200
change
rect2.yProperty()
to
200
}
}.play()
Key frame DSL
108
109. Animation in GroovyFX
timeline(cycleCount:
Timeline.INDEFINITE,
autoReverse:
true)
{
at
(1000.ms)
{
change(rect1,
'x')
to
200
tween
ease_both
change
rect2.yProperty()
to
200
tween
linear
}
}.play()
Optional easing
109
110. Event Listeners in GroovyFX
> 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()
}
110
111. Event Listeners in GroovyFX
Supported
using
the
built-‐in
Closure
syntax
Optional
arguments
for
event
objects
onMouseClicked
{
MouseEvent
e
-‐>
timeline
{
at(3.s)
{
change
e.source.radiusProperty()
to
0
}
}.play()
}
Compact syntax
{body}
111
112. Event Listeners in GroovyFX
Supported
using
the
built-‐in
Closure
syntax
Optional
arguments
for
event
objects
Optional event parameter
{event -> body}
onMouseClicked
{
MouseEvent
e
-‐>
timeline
{
at(3.s)
{
change
e.source.radiusProperty()
to
0
}
}.play()
}
112
113. TableView in Java
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);
113
123. What is Scala
2001 2006
• Scala Started • Scala v2.0
2003/2004 2011
• Scala v1.0 • Scala 2.9.0 (latest)
> Started in 2001 by Martin Odersky
> Compiles to Java bytecodes
> Pure object-oriented language
> Also a functional programming language
123
124. Why Scala?
> Shares many language features with JavaFX Script
that make GUI programming easier:
l Static Type Checking – Catch your errors at compile
time
l Closures – Wrap behavior and pass it by reference
l Declarative – Express the UI by describing what it
should look like
> Scala also supports Type Safe DSLs!
l Implicit Conversions – type safe class extension
l Operator Overloading – with standard precedence rules
l DelayedInit / @specialized – advanced language
features
124
125. Java vs. Scala DSL
public
class
HelloStage
extends
Application
{
object
HelloJavaFX
extends
JFXApp
{
stage
=
new
Stage
{
public
void
start(Stage
stage)
{
title
=
"Hello
Stage"
stage.setTitle("Hello
Stage");
width
=
600
stage.setWidth(600);
height
=
450
stage.setHeight(450);
scene
=
new
Scene
{
Scene
scene
=
new
Scene();
fill
=
LIGHTGREEN
scene.setFill(Color.LIGHTGREEN);
content
=
Seq(new
Rectangle
{
21 Lines
Rectangle
rect
=
new
Rectangle();
rect.setX(25);
rect.setY(40);
17 Lines
x
=
25
y
=
40
width
=
100
430 Characters
rect.setWidth(100);
rect.setHeight(50);
177 Characters
height
=
50
fill
=
RED
rect.setFill(Color.RED);
})
scene.setRoot(new
Group(rect));
}
stage.setScene(scene);
}
stage.show();
}
}
public
static
void
main(String[]
args)
{
launch(HelloStage.class,
args);
}
}
125
126. Disappearing Circles in ScalaFX
object
DisappearingCircles
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)
}
}
}
}
127. Disappearing Circles in ScalaFX
object
DisappearingCircles
extends
JFXApp
{
stage
=
new
Stage
{
title
=
"Disappearing
Circles"
width
=
800
height
=
600
Base class for JavaFX
scene
=
new
Scene
{
applications
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)
}
}
}
}
127
128. Disappearing Circles in ScalaFX
object
DisappearingCircles
extends
JFXApp
{
stage
=
new
Stage
{
title
=
"Disappearing
Circles"
width
=
800
Declarative Stage
height
=
600
scene
=
new
Scene
{
definition
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)
}
}
}
}
128
129. Disappearing Circles in ScalaFX
object
DisappearingCircles
extends
JFXApp
{
stage
=
new
Stage
{
title
=
"Disappearing
Circles"
Inline property
width
=
800
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)
}
}
}
}
129
130. Disappearing Circles in ScalaFX
object
DisappearingCircles
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)
}
}
}
}
130
131. 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"
131
132. 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();
132
133. 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();
JavaFX Script-like animation
syntax: at (duration) {keyframes}
133
134. 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
134
135. 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
135
136. Event Listeners in Scala
> Supported using the built-in Closure syntax
> Optional arguments for event objects
> 100% type-safe
onMouseClicked
=
{
Timeline(at(3
s){radius-‐>0}).play()
}
136
137. Event Listeners in Scala
Supported
using
the
built-‐in
Closure
syntax
Optional
arguments
for
event
objects
100%
type-‐safe
onMouseClicked
=
{
Timeline(at(3
s){radius-‐>0}).play()
}
Compact syntax
{body}
137
138. Event Listeners in Scala
Supported
using
the
built-‐in
Closure
syntax
Optional
arguments
for
event
objects
100%
type-‐safe
Optional event parameter
{(event) => body}
onMouseClicked
=
{
(e:
MouseEvent)
=>
Timeline(at(3
s){radius-‐>0}).play()
}
138
139. About Project Visage
> “Visage is a domain specific language (DSL)
designed for the express purpose of writing
user interfaces.”
> Visage project goals:
l Compile to JavaFX Java APIs
l Evolve the Language (Annotations, Maps, etc.)
l Support Other Toolkits
> Come join the team!
> For more info: http://visage-lang.org/
139
144. Visage and JavaFX 2.0 are made for
each other…
> Enhanced Binding
l Retains lazy evaluation properties with additional
expressive power
> Integrated Collections
l Sequences and Maps automatically convert
between JavaFX Observable Lists/Maps
> Built-in Animation Syntax
l Ties into JavaFX animation subsystem
l Provides consistent, clean APIs
144
145. Conclusion
> You can write JavaFX applications in
pure Java
> JavaFX is also usable in alternate
languages
> You can get improved support using
DSL libraries
l GroovyFX
l ScalaFX
> Or a dedicated UI JVM Language
l Visage
146. Pro JavaFX 2 Platform Coming Soon!
> Coming 1st Quarter 2012
> All examples rewritten in
Java
> Covers the new JavaFX 2.0
APIs
> Will includes ScalaFX,
GroovyFX, and Visage
146
147. Professional Services
peter.pilgrim@gmail.com
JavaFX 2.0 in Enterprises
Financial Services in London
Training with Consultancy
Technical Leadership
147
148. JavaFX 2.0 – A Java Developer's Guide
Thank You
Stephen Chin Peter Pilgrim
Chief Agile Methodologist, GXS Oracle Java Champion
http://steveonjava.com @steveonjava http://www.xenonique.co.uk/blog/ @peter_pilgrim
149. Attributions
All images are Creative Commons (CC) License from Flickr.com
– “You must attribute the source and you cannot change the content”
Tim Ellis http://www.flickr.com/photos/tim_ellis/
Lego Basics http://www.flickr.com/photos/tim_ellis/338755101/sizes/l/
*PaysImaginaire* http://www.flickr.com/photos/nevrlndtink/
Variable Plastic Bag http://www.flickr.com/photos/nevrlndtink/232906118/sizes/m/
~Deiby http://www.flickr.com/photos/deiby/
Expression http://www.flickr.com/photos/deiby/5489382677/sizes/l/
Lisa Sinclair http://www.flickr.com/photos/plumandjello/
fruit http://www.flickr.com/photos/plumandjello/2333263539/sizes/l/
Nerovivo http://www.flickr.com/photos/dominik99/
http://www.flickr.com/photos/dominik99/407716865/sizes/z/in/photostream/
150. Attributions
All images are Creative Commons (CC) License from Flickr.com
– “You must attribute the source and you cannot change the content”
.Guilty http://www.flickr.com/photos/roll_initiative/
Arbitrary Function Generator http://www.flickr.com/photos/roll_initiative/3278642272/
Loop Oh Rupert Grazer http://www.flickr.com/photos/loop_oh/
Pattern at the Senckenberg Museum in Frankfurt am Main / Germany. http://www.flickr.com/photos/loop_oh/4571485915/
Lili Vieira de Carvalho, Vancouver, Canada http://www.flickr.com/people/lilivc/
Composition of Bowls http://www.flickr.com/photos/lilivc/367582911/sizes/l/
Mykl Roventine http://www.flickr.com/people/myklroventine/
19/365 Game Over http://www.flickr.com/photos/myklroventine/3210068573/sizes/l/
superciliousness / Bentley Smith http://www.flickr.com/people/superciliousness/
200510 carpenter's tools - inside the workman's shed - all his old tools
http://www.flickr.com/photos/superciliousness/57486288/
151. Attributions
All images are Creative Commons (CC) License from Flickr.com
– “You must attribute the source and you cannot change the content”
You’ve got a fast car http://www.flickr.com/photos/coreforce/5910961411/
Core Force http://www.flickr.com/photos/coreforce/
GAME AT MARBLES http://www.flickr.com/photos/9619972@N08/928099769/sizes/l/in/photostream/
(Author unknown, from an antique children's boo
Lucs Game http://www.flickr.com/photos/9619972@N08/928099769/
just.Luc http://www.flickr.com/people/9619972@N08/
DIY Easel http://www.flickr.com/photos/68888883@N00/2744696593/in/photostream/
Judy of the Woods http://www.flickr.com/people/68888883@N00/