developing rias on a variety of clients using javafx ...presented by the pro javafx™ book...

Post on 25-Apr-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Presented by the Pro JavaFX™ book co-authors:James L. Weaver - Veriana Networks, Inc.Weiqi Gao - Object Computing, Inc. Stephen Chin - Inovis, Inc.Dean Iverson - Virginia Tech Transportation Institute

DEVELOPING RIAs ON A VARIETY OF CLIENTS USING JavaFX™ TECHNOLOGY

Sun Confidential: Internal Only

Agenda/Goal: Internalize this Concept Map!

Sun Confidential: Internal Only

About the Lead Instructor

Sun Confidential: Internal Only

Pro JavaFX Platform

• Written by your instructors:

> Jim Weaver > Weiqi Gao > Stephen Chin> Dean Iverson

• Available as an eBook today• Print version ships in June• Chapters on:

> Mobile Development> Advanced Layouts> Back-end Integration> WidgetFX/JFXtras

Sun Confidential: Internal Only

BookStoreFX: Collaborate w/Graphics Designer

Sun Confidential: Internal Only

BookStoreFX: Invoke Web Services

Sun Confidential: Internal Only

DrawFX: JavaFX Mobile Application Demo

Sun Confidential: Internal Only

JavaFX Tools and Resources

Sun Confidential: Internal Only

Start Here: JavaFX.com

Sun Confidential: Internal Only

JavaFX API Docs

Sun Confidential: Internal Only

Expressing The UI Scene Graph

Sun Confidential: Internal Only

Hello Earthrise

Sun Confidential: Internal Only

Hello Earthrise

Creating a StageStage { title: "Hello Earthrise" scene: Scene { …some code omitted… }}

Sun Confidential: Internal Only

Hello Earthrise

Adding a Scenescene: Scene { content: [ ImageView { …some code omitted… }, Group { …some code omitted… } ]}

Sun Confidential: Internal Only

Hello Earthrise

Displaying ImagesImageView { image: Image { url: "http://projavafx.com/images/earthrise.jpg" }},

Sun Confidential: Internal Only

Hello Earthrise

Displaying Text in a GroupGroup { layoutX: 50 layoutY: 180 content: [ textRef = Text { layoutY: 100 textOrigin: TextOrigin.TOP textAlignment: TextAlignment.JUSTIFY wrappingWidth: 380 content: "Earthrise at Christmas: " …some code omitted… fill: Color.rgb(187, 195, 107) font: Font.font("SansSerif", FontWeight.BOLD, 24); } ] clip: Rectangle { width: 430 height: 85 }}

Sun Confidential: Internal Only

Hello Earthrise

Animating Graphicsvar transTransition = TranslateTransition { duration: 60s node: bind textRef toY: -700 interpolator: Interpolator.LINEAR repeatCount: Timeline.INDEFINITE}

Sun Confidential: Internal Only

Building Hello Earthrise with NetBeans

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Building with NetBeans (cont)

Sun Confidential: Internal Only

Dragging an Applet from Browser

Sun Confidential: Internal Only

UI Controls

Sun Confidential: Internal Only

More Cowbell!

Sun Confidential: Internal Only

Opening a Project in NetBeans

Sun Confidential: Internal Only

Expressing the UI, and BindingStage { def acModel = AudioConfigModel { selectedDecibels: 35 } title: "Audio Configuration" scene: Scene { content: [ ...some code omitted... Text { ..some code omitted... content: bind "{%1.0f acModel.selectedDecibels} dB" font: Font.font("SansSerif", FontWeight.BOLD, 18) }, Slider { ..some code omitted... disable: bind acModel.muting min: bind acModel.minDecibels max: bind acModel.maxDecibels value: bind acModel.selectedDecibels with inverse }, ...some code omitted... CheckBox { layoutX: 280 layoutY: 113 selected: bind acModel.muting with inverse }, ...some code omitted... SwingComboBox { ..some code omitted... items: bind for (genre in acModel.genres) { SwingComboBoxItem { text: genre } } selectedIndex: bind acModel.selectedGenreIndex with inverse } ] }}

Sun Confidential: Internal Only

Styling UI Controls / Flow Layout

Sun Confidential: Internal Only

on replace Triggers

Sun Confidential: Internal Only

Defining the Model, and Triggerspublic class AudioConfigModel { public var minDecibels:Number; public var maxDecibels:Number = 160; public var selectedDecibels:Number; public var muting:Boolean; // false is default for Boolean public var genres = [ "Chamber", "Country", "Cowbell", "Metal", "Polka", "Rock" ]; public var selectedGenreIndex:Integer on replace { if (genres[selectedGenreIndex] == "Chamber") { selectedDecibels = 80; } else if (genres[selectedGenreIndex] == "Country") { selectedDecibels = 100; } else if (genres[selectedGenreIndex] == "Cowbell") { selectedDecibels = 150; } else if (genres[selectedGenreIndex] == "Metal") { selectedDecibels = 140; } else if (genres[selectedGenreIndex] == "Polka") { selectedDecibels = 120; } else if (genres[selectedGenreIndex] == "Rock") { selectedDecibels = 130; } };}

Sun Confidential: Internal Only

Transforms, Transitions, Timelines

Sun Confidential: Internal Only

Timeline Animation

Sun Confidential: Internal Only

Defining a Timeline

var startXVal:Number = 100;var anim = Timeline { autoReverse: true keyFrames: [ KeyFrame { time: 0s values: startXVal => 100 }, KeyFrame { time: 1s values: startXVal => 300 tween Interpolator.LINEAR } ] repeatCount: Timeline.INDEFINITE};

Sun Confidential: Internal Only

Expressing the Metronome UI / HBox Layout

Stage { title: "Metronome 1" width: 400 height: 500 visible: true scene: Scene { content: [ Line { startX: bind startXVal startY: 50 endX: 200 endY: 400 strokeWidth: 4 stroke: Color.BLUE }, HBox { layoutX: 60 layoutY: 420 spacing: 10 content: [

Sun Confidential: Internal Only

Expressing the Metronome UI (cont.)

Button { text: "Start" disable: bind anim.running action: function():Void { anim.playFromStart(); } }, Button { text: "Pause" disable: bind anim.paused or not anim.running action: function():Void { anim.pause(); } }, Button { text: "Resume" disable: bind not anim.paused action: function():Void { anim.play(); } }, Button { text: "Stop" disable: bind not anim.running action: function():Void { anim.stop(); } } ] //content } //HBox

Sun Confidential: Internal Only

Defining a Timeline – Short Form

var anim = Timeline { autoReverse: true keyFrames: [ at(0.0s) { startXVal => 100 }, at(1.0s) { startXVal => 300 tween Interpolator.LINEAR} ] repeatCount: Timeline.INDEFINITE};

Sun Confidential: Internal Only

Using Sequences

Sun Confidential: Internal Only

• Represents collections of homogeneous data

• A fundamental container data type• Rich set of language facilities• Contributor to declarative syntax

JavaFX Script Sequences (W-1)

Sun Confidential: Internal Only

• For non sequence type Foo, sequence of Foo is Foo[]

• No nested sequences (sequence of sequences)

• Sequence of sequences is flattened

• The empty sequence is []• Sequences do not have holes: [A, null, B] is

same as [A, B]

Sequence Data Type (W-2)

Sun Confidential: Internal Only

• Explicit sequence expression> [1, 3, 5, 7, 9]> Elements are separated by commas> Comma may be omitted if element ends with

brace

Creating Sequences (W-3)

Sun Confidential: Internal Only

• Numeric sequence with range expressions

> [1..10]> Can have a step: [1..10 step 2], [0.0..0.9 step 0.1]> Can be decreasing: [10..1 step -3] is [10, 7, 4, 1]> Beware of step that goes opposite direction: [10..1] is []> Exclusive right end [1..<5] is [1, 2, 3, 4]

Creating Sequences (W-4)

Sun Confidential: Internal Only

• ints = [1, 3, 5, 7, 9]> sizeof ints is 5> ints[0] is 1, ints[1] is 3, ..., ints[4] is 9> ints[-1] is 0 (default value of Integer), so is ints[5]

> For sequence of objects, default is null

Getting Information From Sequences (W-5)

Sun Confidential: Internal Only

• ints = [1, 3, 5, 7, 9]> ints[0..2] is [1, 3, 5]> ints[0..<2] is [1, 3]> ints[2..] is [5, 7, 9]> ints[2..<] is [5, 7]> ints[2..0], ints[-2..-1], ints[5..6]

are all []s

Getting Slices From Sequences (W-6)

Sun Confidential: Internal Only

• ints = [1, 3, 5, 7, 9]> ints[k | k > 6] is [7, 9] (k > 6 is a

condition)> ints[k | indexof k < 2] is [1, 3]> ints[k | k > 10] is []

Getting Subset From Sequences (W-7)

Sun Confidential: Internal Only

• ints = [1, 3, 5, 7, 9]> insert 20 into ints: ints becomes [1, 3, 5, 7, 9, 20]

> insert 30 before ints[2]: ints becomes [1, 3, 30, 5, 7, 9, 20]

> insert 40 after ints[4]: 40 will be after 7

> insert [50, 60] into ints: result is a flat sequence

Altering Sequences (W-8)

Sun Confidential: Internal Only

• ints = [1, 3, 5, 7, 9]> delete 7 from ints: ints becomes [1, 3, 5, 9] (all 7's will be gone)

> delete ints[0]: ints becomes [3, 5, 9]

> delete ints[0..1]: ints becomes [9]> delete ints: ints becomes [] (delete all

elements)

Altering Sequences (W-9)

Sun Confidential: Internal Only

Binding to the Model

Sun Confidential: Internal Only

• A variable or a constant can be bound to an expression> var x = bind a + b;

• The bound expression is remembered• The dependencies of the expression is watched• Variable is updated

> Regular binding: when dependencies change values

> Laze binding: when variable is accessed> var x = bind lazy a+ b;

Data Binding (W-10)

Sun Confidential: Internal Only

• var x = bind if(a) then b else c> x is updated if a or b or c changes

• var x = bind for (i in [a..b]) { i * i }> Not everything is recalculated> If a = 1 and b = 2, x is [1, 4]> If b changes to 3, only added element is calculated

Binding to Expressions (W-11)

Sun Confidential: Internal Only

• Binding to a block> Bound block may contain any number of defs

followed by one expression> Dependencies of block is backtraced from the

expression• Binding to function invocation expression

> Regular function: dependencies are parameters> Bound function: backtraced from final expression

inside function

Binding to Expressions (W-12)

Sun Confidential: Internal Only

• var a = 3; var b = 4;> var p = bind Point { x: a, y: b };> var q = bind Point { x: bind a, y: b };> var r = bind Point { x: bind a, y: bind b };

• When a change, p get a new instance of Point> q and r keeps the old instance with a new x value

• r will never get a new instance of Point> Outer bind is useless

Binding to Object Literals (W-13)

Sun Confidential: Internal Only

Binding to Functions Example

class CircleModel { var diameter:Number; bound function getArea():Number { Math.PI * Math.pow(diameter / 2, 2); }}Stage { def cModel = CircleModel {}; var sliderRef:Slider; scene: Scene { ...code omitted... content: [ Circle { ...code omitted... radius: bind cModel.diameter / 2 ...code omitted... }, Text { ...code omitted... content: bind "Diameter: {%3.0f cModel.diameter}" }, Text { ...code omitted... content: bind "Area: {%3.2f cModel.getArea()}" }, sliderRef = Slider { ...code omitted... value: bind cModel.diameter with inverse } ] }}

Sun Confidential: Internal Only

Input Event Handling

Sun Confidential: Internal Only

Mobile Equalizer: Mouse Events / Sequences / Bindvar levels: Number[] = [30, 40, 50, 45, 35];var selectedBarIndex: Integer = 0;def MAX_LEVEL: Number = 230;def MIN_LEVEL:Number = 10;var groupRef: Group; ...code omitted... groupRef = Group { focusTraversable: true content: bind for (level in levels) Rectangle { x: 0 y: 60 + (indexof level * 30) width: level height: 20 fill: LinearGradient { ...code omitted... } opacity: if (indexof level == selectedBarIndex) 1 else 0.7 onMousePressed: function(me:MouseEvent):Void { selectedBarIndex = indexof level; } onMouseDragged: function(me:MouseEvent):Void { if (me.x >= MIN_LEVEL and me.x <= MAX_LEVEL) { levels[indexof level] = me.x; } } } } ...code omitted...

Sun Confidential: Internal Only

Mobile Equalizer: Key Eventsvar levels: Number[] = [30, 40, 50, 45, 35];var selectedBarIndex: Integer = 0;def MAX_LEVEL: Number = 230;def MIN_LEVEL:Number = 10;var groupRef: Group; ...code omitted... groupRef = Group { focusTraversable: true content: bind for (level in levels) ...code omitted... onKeyPressed: function(ke:KeyEvent):Void { if (ke.code == KeyCode.VK_RIGHT and levels[selectedBarIndex] <= MAX_LEVEL - 10) { levels[selectedBarIndex] += 10; } else if (ke.code == KeyCode.VK_LEFT and levels[selectedBarIndex] > MIN_LEVEL + 10) { levels[selectedBarIndex] -= 10; } else if (ke.code == KeyCode.VK_DOWN) { selectedBarIndex = (selectedBarIndex + 1) mod sizeof levels; } else if (ke.code == KeyCode.VK_UP) { selectedBarIndex = (sizeof levels + selectedBarIndex - 1) mod sizeof levels; } } },

Sun Confidential: Internal Only

Layout Management

Sun Confidential: Internal Only

MigLayout (D-0)

Sun Confidential: Internal Only

MigLayout Basics

Flexible Grid-Based Layout

FlowWrap

MigLayout (D-1)

Sun Confidential: Internal Only

MigLayout (D-2)

Layout Constraints Control the Overall Layout

“fill” “wrap”

“flowy” “gap”

MigLayout { constraints: “fill, wrap” // to be continued}

Sun Confidential: Internal Only

MigLayout (D-3)

Row & Column ContraintsSize Types

“[min:pref:max][100:pref:500][3cm!]”

Gap Types“[]5mm[]rel[]unrel[]push[]”

MigLayout { constraints: "fill, wrap" columns: "[][]" rows: "[][]4mm[]push[]" // to be continued}

Sun Confidential: Internal Only

Component Constraints“cell 0 1”“wrap 1cm” “newline 1cm”“grow, push”“span 3”“skip 2”“width min:300:max, height 20mm!”“alignx left”“aligny right”“sizegroup label”

MigLayout (D-4)

Sun Confidential: Internal Only

MigLayout Example (D-1)MigLayout { constraints: "fill, wrap" columns: "[][]" rows: "[][]4mm[]push[]" content: [ Label { text: "Email" layoutInfo: nodeConstraints( "ax right" ) } TextBox { layoutInfo: nodeConstraints( "growx, pushx" ) } Label { text: "Password" layoutInfo: nodeConstraints( "ax right" ) } TextBox { layoutInfo: nodeConstraints( "growx, pushx" ) } Button { text: "Login" layoutInfo: nodeConstraints( "skip, right" ) } Label { text: "This text is 'pushed' to the bottom" layoutInfo: nodeConstraints( "span" ) } ]}

Sun Confidential: Internal Only

• But Wait, There's More!

MigLayout (D-5)

“dock north” (or south, east, west)

"pos 0 0 container.x2 container.y2"

Sun Confidential: Internal Only

Playing Media

Sun Confidential: Internal Only

Media (D-6)

Sun Confidential: Internal Only

Media (D-6)

Sun Confidential: Internal Only

Sources

Media (D-6)

file://path/to/media/file.wav

http://path/to/media/file.wmv

Sun Confidential: Internal Only

Media (D-7)

Sun Confidential: Internal Only

Media (D-8)

MediaPlayer { media: Media { source: “file://my/audio/file.mp3” } onError: function( me:MediaError ) { println( "Error Occurred: {me.message}" ); }}.play();

Sun Confidential: Internal Only

Media (D-8)

Stage { title: "BasicMoviePlayer" scene: Scene { content: MediaView { fitWidth: 640 fitHeight: 352 mediaPlayer: MediaPlayer { autoPlay: true media: Media { source: "http://www.projavafx.com/movies” “elephants-dream-640x352.flv" } } } }}

Sun Confidential: Internal Only

Communicating with Application Services

Sun Confidential: Internal Only

Who is my Representative: JSON and XML Parsing

Sun Confidential: Internal Only

• Think Resources• Requests

– POST = Create– GET = Retrieve– PUT = Update– DELETE = Delete

Consuming Web Services (D-9)

RESTful Web Services

Sun Confidential: Internal Only

• HttpRequest> Lifecycle of a GET Request

– started true– connecting true– readingHeaders true– responseCode 200– responseMessage “Ok”– doneHeaders true– reading true– toRead 314 – read 0 – 314– input stream– doneRead true– done true

Consuming Web Services (D-10)

Sun Confidential: Internal Only

Consuming Web Services (D-10)

HttpRequest { location: "http://www.projavafx.com" onInput: function( inputStream:java.io.InputStream ) { var br:BufferedReader; try { br = new BufferedReader( new InputStreamReader( inputStream ) ); var line = br.readLine(); while (line != null) { println( line ); line = br.readLine(); } } finally { if (br != null) { br.close(); } else { inputStream.close(); } } }}.start();

• HttpRequest

Sun Confidential: Internal Only

Responses> XML

> JSON

Consuming Web Services (D-9)

{ "elements" : [ { "symbol" : "H", "name" : "Hydrogen", "atomicNumber" : 1 }, { "symbol" : "He", "name" : "Helium", "atomicNumber" : 2 }, ]}

<?xml version="1.0" ?><elements> <element> <symbol>H</symbol> <name>Hydrogen</name> <atomicNumber>1</atomicNumber> </element> <element> <symbol>He</symbol> <name>Helium</name> <atomicNumber>2</atomicNumber> </element></elements>

Sun Confidential: Internal Only

• PullParser> Multi-Format Parser> Event Driven vs Pull Parsing

Consuming Web Services (D-11)

Sun Confidential: Internal Only

• Parsing JSON

Consuming Web Services (D-12)

try { var parser = PullParser { input: inputStream documentType: PullParser.JSON; onEvent: function( e:Event ) { print( "{%-20s e.typeName} {%-20s e.name}" ); if (e.name == "atomicNumber" ) { println( "{%-20d e.integerValue}" ); } else { println( "{%-20s e.text}" ); } } } parser.parse();} finally { inputStream.close();}

Event Type Event Name Data========== ========== ====START_DOCUMENTSTART_ELEMENTSTART_VALUE elementsSTART_ARRAY elementsSTART_ARRAY_ELEMENT elementsSTART_ELEMENTSTART_VALUE symbolTEXT symbol HEND_VALUE symbol HSTART_VALUE nameTEXT name HydrogenEND_VALUE name HydrogenSTART_VALUE atomicNumber 0INTEGER atomicNumber 1END_VALUE atomicNumber 1END_ELEMENTEND_ARRAY_ELEMENT

Sun Confidential: Internal Only

• Parsing XML

Consuming Web Services (D-13)

try { var parser = PullParser { input: inputStream documentType: PullParser.XML; onEvent: function( e:Event ) { println( "{%-20s e.typeName} {%-20s e.qname.name} “ “{%-20s e.text}" ); } } parser.parse();} finally { inputStream.close();}

Event Type Event Name Data========== ========== ====START_DOCUMENT nullSTART_ELEMENT elementsSTART_ELEMENT elementSTART_ELEMENT symbolTEXT symbol HEND_ELEMENT symbol HSTART_ELEMENT nameTEXT name HydrogenEND_ELEMENT name HydrogenSTART_ELEMENT atomicNumberTEXT atomicNumber 1END_ELEMENT atomicNumber 1END_ELEMENT element 1

Sun Confidential: Internal Only

Creating Custom UI Components

Sun Confidential: Internal Only

Extending CustomNodepublic class ColorPickerNode extends CustomNode { def rgbNums: Number[] = [0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF]; override public function create():Node { Group { content: bind for (rNum in rgbNums) { Group { def SQUARE_WIDTH: Number = 15 layoutY: indexof rNum * (SQUARE_WIDTH * sizeof rgbNums + SQUARE_WIDTH) content: for (gNum in rgbNums) { for (bNum in rgbNums) { Group { var rectRef: Rectangle content: [ rectRef = Rectangle { x: indexof gNum * SQUARE_WIDTH y: indexof bNum * SQUARE_WIDTH width: SQUARE_WIDTH height: SQUARE_WIDTH fill: Color.rgb(rNum, gNum, bNum) }, Text { textOrigin: TextOrigin.BOTTOM visible: bind rectRef.hover font: Font.font("Sans serif", FontWeight.BOLD, 14) content: "rNum:{%1.0f rNum}, " "gNum: {%1.0f gNum}, " "bNum: {%1.0f bNum}" ...

Sun Confidential: Internal Only

JavaFX Community

Sun Confidential: Internal Only

Layout Insert

This isn't in your printouts(you can stop flipping pages...)

Sun Confidential: Internal Only

JavaFX 1.2 Standard Layouts● HBox● VBox● Flow● ClipView● Stack● Tile

Sun Confidential: Internal Only

JavaFX 1.2 Custom Layouts● Container● Panel

● Both Extend Parent● Container creates layouts by extension● Panel creates layouts by declaration

Sun Confidential: Internal Only

(S-1)

WidgetFX and JFXtrasOpen-Source JavaFX

Sun Confidential: Internal Only

WidgetFX Features (S-2)

Open-Source◦ WidgetFX is a fully open-source widget platform (widgets

themselves can be licensed commercially). Cross-Platform Support

◦ WidgetFX runs on all major platforms including Windows XP/Vista, Linux, and Mac OS X.

One-Click Installation◦ WidgetFX takes advantage of Java Web Start to provide one-

click installation and automatic updates of the dock and widgets.

Rich Desktop Applications◦ WidgetFX leverages the full power of Java and JavaFX

providing a very rich library of graphics, animation, and media capabilities.

Embedded Flash Widgets◦ Easy migration path for developers currently using Flash or

Flex.

Sun Confidential: Internal Only

Built-in Widgets (S-3)

Clock◦ Skinnable via CSS

Slide Show◦ Configurable Directory, Speed, & Filter

Web Feed◦ Supports Atom and all RSS flavors

Sun Confidential: Internal Only

Dock Features (S-4)

Drag to desktop Resize widgets (option for fixed aspect ratio) Per widget transparency Widget settings saved on restart Toggle dock always-on-top Launch on start-up Multi-monitor support Dock and widgets can be styled via CSS

Sun Confidential: Internal Only

Movie Widget Tutorial

(S-5)

Sun Confidential: Internal Only

Widget Properties (S-6)

Name Type Inherited From Descriptionwidth Number Resizable Initial width of the widgetheight Number Resizable Initial height of the widgetaspectRatio Number Widget If set, defines a fixed aspect

ratio for the widget width and height

skin Skin Control Renders the widget to the scene graph, can have CSS properties for styling

Sun Confidential: Internal Only

Widget Definition (S-7)

var widget: Widget;widget = Widget { width: 640 height: 352 aspectRatio: bind player.media.width / player.media.height skin: Skin { scene: Group { content: bind player } }}

Sun Confidential: Internal Only

Load the Media (S-8)

var source = "http://projavafx.com/movies/elephants-dream-640x352.flv";var player = bind SimpleMoviePlayer { media: Media { source: source } width: bind widget.width height: bind widget.height}

Sun Confidential: Internal Only

Run as Application (S-9)

Sun Confidential: Internal Only

Run in Widget Runner (S-10)

Sun Confidential: Internal Only

How the Widget Runner Works (S-11)

Test widgets standalone Identical behavior to production Two ways to launch:

◦ Automatic Execution Run your widget as a Web Start application

◦ Direct Execution Create a launch url with the following structure:

http://widgetfx.org/dock/runner.jnlp?arg=<widgetUrl>

Sun Confidential: Internal Only

Widget Configuration Properties (S-12)

Class Name Type DescriptionBooleanProperty Boolean This class allows you to persist BooleansBooleanSequenceProperty Boolean[] This class allows you to persist sequences

of Booleans

IntegerProperty Integer This class allows you to persist IntegersIntegerSequenceProperty Integer[] This class allows you to persist sequences

of Integers

LongProperty Long This class allows you to persist LongsLongSequenceProperty Long[] This class allows you to persist sequences

of Longs

NumberProperty Number This class allows you to persist NumbersNumberSequenceProperty Number[] This class allows you to persist sequences

of Numbers

StringProperty String This class allows you to persist StringsStringSequenceProperty String[] This class allows you to persist sequences

of Strings

Sun Confidential: Internal Only

Widget Configuration (S-13)

widget = Widget { ... configuration: Configuration { properties: [ StringProperty { name: "source" value: bind source with inverse } ] scene: Scene {} // defined in the next // code fragment }}

Sun Confidential: Internal Only

Widget Config Dialog (S-14)

scene: Scene { content: Grid { rows: row([ Text { content: "Source URL:" }, TextBox { columns: 30, value: bind source with inverse } ]) }}

Sun Confidential: Internal Only

Add an On-Replace Trigger (S-15)

var player = bind SimpleMoviePlayer { media: Media { source: source } width: bind widget.width height: bind widget.height} on replace = oldPlayer { oldPlayer.player.stop(); }

Sun Confidential: Internal Only

Widget Configuration (demo) (S-16)

Sun Confidential: Internal Only

Community Written Widgets (S-17)

•Disk Space• Pär Dahlberg

•World Clock• Ludovic Hochet

•Audio Config / Presentation Cube• Jim Weaver

•Weather Widget• Larry Dickson

Sun Confidential: Internal Only

JFXtras (S-18)

JFXtras

Utilities and Add-ons for JavaFX

Sun Confidential: Internal Only

JFXtras Highlights (S-19)

Dialogs Layouts

◦ JFXtras Grid◦ MigLayout

Testing◦ Declarative◦ Supports Behavior Driven Development (BDD)◦ Fluent (ala. Hamcrest, Fest Assert)

Shape Support◦ Thanks to Andres Almiray (jSilhouette) and Steve Bixby

Asynchronous Worker◦ You deserve your share of rope!

Borders

Sun Confidential: Internal Only

Grid Sample (S-20)

JFXDialog { title: “Grid Sample" packed: true scene: ResizableScene { content: Grid { var list = SwingList { items: for (i in [1..10]) SwingListItem { text: "List item {i}"; } } rows: [row([Text {content: "Two Text Boxes:"}, TextBox {}, TextBox {}]),row([Text {content: "List:"}, Cell {content: list, hspan: 3}])

Sun Confidential: Internal Only

Grid Sample (output) (S-21)

Sun Confidential: Internal Only

Unit Test Sample 1 (S-24)

Test { say: "Sequence Utils" test: [ Test { say: "should add numbers" do: function() { SequenceUtil.sum([10.4, 20.3]); } expect: closeTo(30.7)

Sun Confidential: Internal Only

Unit Test Sample 2 (S-25)

Test { say: "We should be able to convert from" var canonicalJavaFXPoint = Point2D {x: 1, y: 2}; var canonicalJavaPoint = new java.awt.Point(1, 2); test: [ Test { say: "a JavaFX point to a Java point" do: function() { GeometryUtil.pointToJava(canonicalJavaFXPoint); } expect: [ instanceOf("java.awt.geom.Point2D"), equalTo(canonicalJavaPoint) ] },

Sun Confidential: Internal Only

Unit Test Sample (parameterized) (S-26)

Test { say: "should be able to multiply“ test: [ for (i in [0..9]) { Test { assume: that(i*1.5, closeTo(floor(i*1.5))) say: "{i} x 1.5 without a decimal" do: calculator.multiply(i, 1.5) expect: equalTo("{(i*1.5) as Integer}") } } ]}.perform();

Sun Confidential: Internal Only

Shape Support (S-27)

New Shapes:◦ Almond◦ Arrow◦ Asterisk◦ Astroid◦ Balloon◦ Cross◦ Donut◦ Fan◦ Lauburu◦ MultiRoundRectangle◦ Rays◦ RegularPolygon◦ ReuleauxTriangle◦ RoundPin◦ Star◦ Triangle

Sun Confidential: Internal Only

Shape Support (demo) (S-28)

Sun Confidential: Internal Only

Border Support (S-29)

JFXtras Borders:◦ BevelBorder◦ CenteredBorder◦ EllipseBorder◦ EmptyBorder◦ EtchedBorder◦ FrameBorder◦ ImageBorder◦ LineBorder◦ MetallicBorder◦ PipeBorder◦ RoundedRectBorder◦ ShapeBorder◦ SoftBevelBorder◦ TitledBorder

Sun Confidential: Internal Only

Border Support (demo) (S-30)

Sun Confidential: Internal Only

Other JFXtras Goodies (S-31)

JFXObject◦ Convenience method for reflection

JFXException◦ Declaratively define JavaFX exceptions

Geometry Utilities◦ pointToJava/JavaFX, rectangleToJava/JavaFX

Sequence Utilities◦ sum, concat, join, characterSequence

ResizableScene◦ no more binding to stage/scene bounds

Native Menus◦ AWT Menus and Popups

Sun Confidential: Internal Only

2D Drawing and Images

Sun Confidential: Internal Only

Top Ten Excellent New Features in JavaFX 1.2

Sun Confidential: Internal Only

It is great to have some pure JavaFX controls, such as Button, ListView, ProgressBar, and Slider that don’t rely on Swing peers underneath. An added advantage is that they are fully skinnable to match the fonts and color palette of your application.

1. Skinnable UI Controls (D)

Sun Confidential: Internal Only

The new layout classes including Tile, Stack, Flow, ClipView, and Panel are a very welcome addition! The layout API has also gotten a lot cleaner, which makes it easier to write your own layouts, such as the JFXtras Grid.

2. New Layout Classes (J)

Sun Confidential: Internal Only

Now I can compete with my Flex buddies on business oriented RIAs! The new charting and graphing support is a must for any enterprise application, so I am glad to see it made the cut.

3. Charting: Area, Bar, Bubble, Line, Pie, Scatter (D)

Sun Confidential: Internal Only

Having built-in RSS/Atom feed support is a welcome addition, and will make it much easier to write feed-based applications that cleanly port from the desktop to mobile.

4. RSS/Atom Feed Support (D)

Sun Confidential: Internal Only

An easy way to save state between sessions, no Web Start API hacking required! See the new Resource and Storage classes in the javafx.io package for details.

5. Local Data Storage (J)

Sun Confidential: Internal Only

There is some new functionality that makes it easy to pop-up alert dialogs, or work directly with the screen bounds. While you could have done direct Swing/Java2D hacks before, this helps keep your code mobile safe.

6. Stage Infrastructure: Screen and Alerts (J)

Sun Confidential: Internal Only

The new Task class supersedes the AsynchronousAbstractOperation with a clean API for calling long-running tasks. The code running in the background has to be coded in Java, but if you are looking for a JavaFX alternative see the JFXWorker (which is part of the JFXtras project).

7. Improved Asynchronous Processing Model (S)

Sun Confidential: Internal Only

Finally, a high-performance alternative to Gaussian blur. This is now the default for DropShadow, which should speed up a lot of applications!

8. BoxBlur effect (S)

Sun Confidential: Internal Only

There are new JavaFX equivalents for java.lang.Math and java.util.Properties in the javafx.util package. Make sure you use these instead so your application is portable to mobile.

9. Math and Properties Classes (W)

Sun Confidential: Internal Only

The new nativearray support allows Java arrays to be reused from JavaFX code without paying the cost converting to a sequence. In addition, multi-dimensional Java arrays can now be accessed from JavaFX. Here is a sample of the new syntax:

10. Direct Referencing of Java Arrays via nativearray

var packages: nativearray of Package = getPackages();

Sun Confidential: Internal Only

Get a Discount on Our Pro JavaFX 1.2 Book!

Presented by the Pro JavaFX™ book co-authors:James L. Weaver - Veriana Networks, Inc.Weiqi Gao - Object Computing, Inc. Stephen Chin - Inovis, Inc.Dean Iverson - Virginia Tech Transportation Institute

THANKS FOR YOUR ATTENTION!

top related