View
16.788
Download
0
Category
Tags:
Preview:
DESCRIPTION
A University talk about JavaFX 2.0 do
Citation preview
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
Meet the Presenters
Stephen Chin @steveonjava
Motorcyclist
Family Man
Peter Pilgrim @peter_pilgrim
Football, Music & Partner
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
http://blogs.oracle.com/chrisoliver/entry/epitaph 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
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.
Demo Video Fracture
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
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
Windows OS Requirements
Operating System (32-Bit and 64-Bit) Browsers (32-Bit and 64-Bit) Windows XP Home and Professional with Service Pack 3
Internet Explorer 7 and 8 Chrome
Windows Vista Home Basic, Home Premium, Business, and Ultimate with Service Pack 2
Internet Explorer 7, 8, and 9 Firefox 3.5, 3.6, and 4 Chrome
Windows 7 Home Premium, Professional, and Ultimate
Internet Explorer 8 and 9 Firefox 3.5, 3.6, and 4 Chrome
9
Supported Graphics Cards
Graphics Card Supported Graphics Processing 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
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
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(); Scene scene = new Scene(root, 400, 250, Color.ALICEBLUE); Text text = new Text(); 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
19 Lines 425 Characters
Hello Devoxx (Builder Version)
public void start(Stage primaryStage) { primaryStage.setTitle("Hello Devoxx"); primaryStage.setScene(SceneBuilder.create() .width(400) .height(250) .fill(Color.ALICEBLUE) .root( GroupBuilder.create().children( TextBuilder.create() .x(105) .y(120) .text("Hello Devoxx") .font(new Font(30)) .build() ).build() ) .build()); primaryStage.show(); }
13
25 Lines 418 Characters
Hello Devoxx (GroovyFX Version)
GroovyFX.start { primaryStage -‐> def sg = new SceneGraphBuilder() sg.stage( title: 'Hello Devoxx', show: true) { scene( fill: aliceblue, width: 400, height: 250) { text( x: 105, y: 120, text: "Hello Devoxx" font: "30pt") } } }
14
17 Lines 190 Characters
Hello Devoxx (ScalaFX Version)
object HelloDevoxx extends JFXApp { stage = new Stage { title = "Hello Devoxx" width = 400 height = 250 scene = new Scene { fill = BLUE Text { x = 105 y = 120 text = "Hello Devoxx" font = Font(size: 30) } } } }
15
16 Lines 163 Characters
Hello Devoxx (Visage Version)
Stage { title: "Hello Devoxx" width: 400 height: 250 scene: Scene { fill: BLUE content: Text { x: 105 y: 120 text: "Hello Devoxx" font: Font {size: 30pt} } } }
16
14 Lines 129 Characters
Architecture of JavaFX 2.0
Java Virtual Machine
Java2D Open GL D3D
Prism Glass WinTk
Media Engine
Web Engine
JavaFX Public API
Quantum Toolkit
Properties, Lists, Binding 18
JavaFX 2.0 Fundamentals
JavaFX 2.0 Properties
> Primitive Properties > Object Properties > FX List Collection Properties
> Properties are:
l Observable l Lazy l Type Safe
19
Properties in Java
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
Property Declaration
Properties in Java
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; } }
21
Setter Method (Convenience)
Properties in Java
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; } }
22
Getter Method (Convenience)
Properties in Java
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; } }
23
Property Fetcher (Lazy Construction)
Properties in Java
public class Person { private StringProperty firstName; 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
Even Lazier…
Properties in Java
public class Person { private StringProperty firstName; public void setFirstName(String val) { 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
With initial value
Undirectional, Bidirectional and Lazy binding in Java
Demo Properties
Listeners
> Change Listener l Observable, old value, new value
> Invalidation Listeners l Observable
27
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
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
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
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
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
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
Binding in JavaFX 2.0
Infix Addition/Subtraction/Multiplication/Division:
heightProperty().bind(rect1.heightProperty().add(rect2.heightProperty()));
Aggregate Operators:
widthProperty().bind(Bindings.max(rect1.widthProperty(), rect2.widthProperty(), rect3.widthProperty()));
Conditional Expressions:
strokeWidthProperty().bind(Bindings.when(hover).then(4).otherwise(0));
Bidirectional Binding:
heightProperty().bindBidirectional(rect1.heightProperty());
34
Life is like a bowl of cherries
Demo Image Fracture
“The Scene-graph is King.”
36
Image
Image View 1
Image View 2
Image View 3
Image View 4
Image View Node
37
Media Player
Media View 1
Media View 2
Media View 3
Media View 4
Media
38
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)
39
Controls
10 / 10 Break
Button Control
> Simple Button Control > Add and remove click event handler > Support Cascading Style Sheets
41
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
TextField Control
> One line entry text field control > Set OnAction event handler > Can listen to individual key events > Support Cascading Style Sheets
43
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
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
ListView Code
public void initialiseScene(Group root) { VBox vbox = VBoxBuilder.create()
.spacing(25).layoutX(25).layoutY(25).build(); root.getChildren().add(vbox); final ListView<String> listView =
new ListView<String>(); listView.setItems(FXCollections.observableArrayList( "Manchester City", "Manchester United", "Newcastle United", "Chelsea", "Tottenham Hotspur", "Liverpool", /* … */ ));
listView.getSelectionModel() .setSelectionMode(SelectionMode.MULTIPLE); vbox.getChildren().addAll(listView); } /*…*/ }
46
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
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
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
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
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
Progress Bar/Indicator Code
VBoxBuilder.create().spacing(10) .alignment(Pos.CENTER).children( new ProgressBar(), new ProgressBar(.25), new ProgressIndicator(.75) ).build()
52
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
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
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
TabPane Code
Accordion accordion; TitledPane imagePane; TabPane tabPane = TabPaneBuilder.create().tabs( TabBuilder.create().text("Progress").content( /* Progress Tab Here */ ).build(), TabBuilder.create().text("Accordion").content( /* Accordion Tab Here */ ).build() ).build(); accordion.setExpandedPane(imagePane); vbox.getChildren().addAll(tabPane);
56
JavaFX Components
57
Pens, papers and inks, first!
58
A component is an encapsulation that binds a set of nodes with the operations that act on those nodes
59
Component Types
> Non-Resizable l javafx.scene.shape.Shape l javafx.scene.Group
> Resizable l javafx.scene.layout.Pane l javafx.scene.layout.Region l javafx.scene.layout.Control
60
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
61
Region based
> Region is the sub class of javafx.scene.Parent > Adds the ability to resize a node, layout a
particular set of children
62
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
63
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
64
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
65
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
66
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!
67
Layout Methods
protected double computePrefHeight(double w) { return child.prefHeight(w) + 2 *ht; } protected double computePrefWidth(double h) { return child.prefWidth(h) + 2 * wt; }
68
Pedantic Complete
Implement the other four methods too > computeMinWidth(v) > computeMinHeight(v) > computeMaxWidth(v) > computeMaxHeight(v)
69
Demo Custom Border Layout
Writing JavaFX Containers
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
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
Layout Secrets
75
Reuse SDK Methods
Some SDK Methods
> Region#layoutInArea() > Region#positionInArea() > Node#resize() > Node#resizeRelocate()
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
A B
D E
C
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
> AnchorPane > BorderPane > VBox/HBox > FlowPane > StackPane > TilePane > GridPane
Built-in Layouts
Demo Box Container Pane
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)
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
88
Displaying HTML in JavaFX
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
For more info on Web/HTML5…
Moving to the Client – JavaFX and HTML5 Stephen Chin Kevin Nilson Thursday 10:50 AM, Room 7
90
10 / 10 Break
JavaFX With Groovy
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
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) } } }
93
21 Lines 430 Characters
8 Lines 180 Characters
Disappearing Circles in Groovy
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) } } } }
94
Disappearing Circles in Groovy
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) } } } }
95
Builder for GroovyFX scene graphs
Disappearing Circles in Groovy
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) } } } }
96
Declarative Stage definition
Disappearing Circles in Groovy
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) } } } }
97
Inline property definitions
Disappearing Circles in Groovy
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) } } } }
98
Bind to properties
Disappearing Circles in Groovy
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) } } } }
99
Sequence Creation Via Loop
Properties in Java
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; ! }! ! private StringProperty lastName;! public void setLastName(String value)
{ lastNameProperty().set(value); }! public String getLastName() { return lastNameProperty().get(); }! public StringProperty lastNameProperty() { ! if (lastName == null) // etc.! } !}!
100
Properties in GroovyFX
public class Person {! @FXBindable String firstName; ! @FXBindable String lastName;!}!
101
Properties in GroovyFX
public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;!}!
102
Optional initializers
Properties in GroovyFX
public class Person {! @FXBindable String firstName; ! @FXBindable String lastName = “Smith”;!}!!def p = new Person()!def last = p.lastName!p.firstName = “Agent”!!
103
Get and set values
Properties in GroovyFX
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()))!!
104
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) } }
105
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
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()
107
Easy animation syntax: at (duration) {keyframes}
Animation in GroovyFX
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
at (1000.ms) { change(rect1, 'x') to 200 change rect2.yProperty() to 200 } }.play()
108
Key frame DSL
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()
109
Optional easing
Event Listeners in GroovyFX
> Supported using the built-in Closure syntax > Optional arguments for event objects
110
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
111
Compact syntax {body}
onMouseClicked { MouseEvent 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
112
Optional event parameter {event -> body}
onMouseClicked { MouseEvent e -‐> timeline { at(3.s) { change e.source.radiusProperty() to 0 }
}.play() }
TableView in Java
113
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
114
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
115
TextField urlField = new TextField(“h_p://www.google.com”); HBox.setHgrow(urlField, Priority.ALWAYS); HBox hbox = new HBox(); hbox.getChildren().add(urlField); WebView webView = new WebView(); VBox.setVgrow(webView, Priority.ALWAYS); VBox vbox = new VBox(); vbox.getChildren().addAll(hbox, webView);
Layout in GroovyFX
116
sg.stage(title: "GroovyFX WebView 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
117
Layout in GroovyFX
118
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
119
GroovyFX Supports…
120
GroovyFX Supports…
121
122
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
2001 • Scala Started
2003/2004 • Scala v1.0
2006 • Scala v2.0
2011 • Scala 2.9.0 (latest)
123
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
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 }) } } }
125
21 Lines 430 Characters
17 Lines 177 Characters
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) } } } }
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
Base class for JavaFX applications
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) } } } }
128
Declarative Stage definition
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) } } } }
129
Inline property definitions
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) } } } }
130
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"
131
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
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();
133
JavaFX Script-like animation syntax: at (duration) {keyframes}
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();
134
Operator overloading for animation syntax
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();
135
Optional tween syntax
Event Listeners in Scala
> Supported using the built-in Closure syntax > Optional arguments for event objects > 100% type-safe
136
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
137
Compact syntax {body}
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
138
Optional event parameter {(event) => body}
onMouseClicked = { (e: MouseEvent) => Timeline(at(3 s){radius-‐>0}).play() }
About Project Visage
> 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
> “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.”
How about JavaFX on… Visage
Stage { title: "Hello Stage" width: 600 height: 450 scene: Scene { fill: Color.LIGHTGREEN content: Rectangle { x: 25 y: 40 width: 100 height: 50 fill: Color.RED } } }
140
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 } } }
141
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 } } }
142
Visage is JavaFX Script++
> Default Parameters > New Literal Syntax For:
l Angles – 35deg, 4rad, 1turn l Colors – #DDCCBB, #AA33AA|CC l Lengths – 5px, 2pt, 3in, 4sp
> Null-check Dereference l var width = rect!.width
> Built-in Bindable Maps (coming soon!) l var fruitMap = ["red" : apple, "yellow" : banana] l var fruit = bind fruitMap["red"]
143
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
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
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
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
Thank You
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/
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/
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/
Recommended