Post on 25-Apr-2020
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!