Você está na página 1de 73

Plataforma JavaFX 2.

0,
GroovyFX, ScalaFX e Visage
Stephen Chin
Chefe de metodologias Ageis, GXS
steveonjava@gmail.com
tweet: @steveonjava
Translated by Marcelo Quinta
Conheca o palestrante
Stephen Chin
http://steveonjava.com/
Motorcyclist
Family Man
Java Champion
Autor
Pro JavaFX Platform
Pro Android Flash
Fundador de projetos Open
Source
JFXtras
ScalaFX
WidgetFX
Visage
A plataforma JavaFX 2.0
Experiencia imersiva Desktop combinando o
melhor do JavaFX e HTML5
> Use seus conhecimentos Java com as
modernas APIs JavaFX
> Integre Java, JavaScript e HTML5 na mesma
aplicacao
> Nova gama de graficos usa as vantagens de
aceleracao de hardware para aplicacoes 2D e
3D
> Use sua IDE favorita: NetBeans, Eclipse,
IntelliJ, etc.


JavaFX agora e Open Source!
Parte do projeto OpenJDK

Controles disponiveis agora
codigo adicional adicionado
incrementalmente

Pagina do projeto:
> http://openjdk.java.net/projects/openjfx/
4
E vai rodar nos Tablets!
5
> iPad (iOS)
> Linux
(plataforma
popular que
executa algo
semelhante a
Java)
Nenhuma data de release foi anunciada
Construindo Aplicacoes JavaFX
> Pode ser executada no navegador ou no Desktop
> Inclui builders para construcoes declarativas
> Linguagens alternativas tambem podem ser utilizadas para
simplificar a criacao da interface de usuario
GroovyFX
ScalaFX
Visage
6
7
Ola JUG (Versao Java)
public class HelloJUG extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Ola JUG");
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("Ola JUG");
root.getChildren().add(text);
primaryStage.setScene(scene);
primaryStage.show();
}
}
8
Ola JUG (Versao com o Builder)
public void start(Stage primaryStage) {
primaryStage.setTitle("Ola JUG");
primaryStage.setScene(SceneBuilder.create()
.width(400)
.height(250)
.fill(Color.ALICEBLUE)
.root(
GroupBuilder.create().children(
TextBuilder.create()
.x(105)
.y(120)
.text("Ola JUG")
.font(new Font(30))
.build()
).build()
)
.build());
primaryStage.show();
}
9
Ola JUG (Versao GroovyFX)
GroovyFX.start { primaryStage ->
def sg = new SceneGraphBuilder()
sg.stage(
title: 'Ola JUG',
show: true) {
scene(
fill: aliceblue,
width: 400,
height: 250) {
text(
x: 105,
y: 120,
text: "Ola JUG"
font: "30pt")
}
}
}
10
Ola JUG (Versao JavaFX)
object HelloJUG extends JFXApp {
stage = new Stage {
title = "Ola JUG"
width = 400
height = 250
scene = new Scene {
fill = BLUE
Text {
x = 105
y = 120
text = "Ola JUG"
font = Font(size: 30)
}
}
}
}
11
Ola JUG (Versao Visage)
Stage {
title: "Ola JUG"
width: 400
height: 250
scene: Scene {
fill: BLUE
content: Text {
x: 105
y: 120
text: "Ola JUG"
font: Font {size: 30pt}
}
}
}
Mostrando HTML no JavaFX
public class WebViewTest extends Application {
public static void main(String[] args) {
launch(WebViewTest.class, args);
}
@Override public void start(Stage stage) {
WebView webView = new WebView();
webView.getEngine().load("http://google.com");
Scene scene = new Scene(webView);
stage.setScene(scene);
stage.setTitle("Web Test");
stage.show();
}}
12
Mostrando HTML no JavaFX
13
Chamando Javascript pelo JavaFX
String script = "alert('Aooo Goiania!');;
eng.executeScript(script);
14
Respondendo a eventos do browser
Eventos suportados:
> Alert/Confirm/Prompt:
Responda funcoes do Javascript de interacao do usuario
> Resize:
Web page move-se ou rearranja ao tamanho da janela
> Status
Web page muda o texto do status
> Visibility
Esconde ou mostra algum objeto da janela
> Popup
Cria uma segunda janela
15
Demo de integracao HTML5/JavaFX
16
JavaFX com Groovy
Features of Groovy
> Linguagem moderna
Closures
Transforms AST
Linguagem fortemente tipada

> Grande integracao com Java
Muito facil fazer a portabilidade de Java para Groovy

> Sintaxe declarativa com builders GroovyFX
Familiar aos desenvolvedores Groovy e JavaFX Script



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)
}
}
}

19
21 Linhas
430 Caracteres
8 Linhas
180 Caracteres
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)
}
}
}
}
20
21
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)
}
}
}
}
Builder para Scene Graphs do
GroovyFX
22
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)
}
}
}
}
Definicao declarativa do Stage
23
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)
}
}
}
}
Definicao de propriedades
embutdidas
24
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)
}
}
}
}
Bind para propriedades
25
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)
}
}
}
}
Criacao de sequencias via loop
Propriedades em 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.
}
}

26
Propriedades em GroovyFX
public class Person {
@FXBindable String firstName;
@FXBindable String lastName;
}

27
public class Person {
@FXBindable String firstName;
@FXBindable String lastName = Smith;
}

Propriedades em GroovyFX
28
Inicializadores opcionais
public class Person {
@FXBindable String firstName;
@FXBindable String lastName = Smith;
}

def p = new Person()
def last = p.lastName
p.firstName = Agent

Propriedades em GroovyFX
29
Valores get and set
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()))

Propriedades em GroovyFX
30
Acesso a propriedades
embutidas para binding
Binding em 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)
}
}
31
Animation em 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()
32
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()
Animation em GroovyFX
33
Sintaxe facil para animacoes:
at (duration) {keyframes}
timeline(cycleCount: Timeline.INDEFINITE, autoReverse: true) {
at (1000.ms) {
change(rect1, 'x') to 200
change rect2.yProperty() to 200
}
}.play()
Animation em GroovyFX
34
Key frame DSL
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()
Animation em GroovyFX
35
Controle de velocidade opcional
Event Listeners em GroovyFX
36
> Sintaxe para Closure usando controles embutidos
> Argumentos opcionais para eventos
onMouseClicked { e ->
timeline {
at(3.s) { change e.source.radiusProperty() to 0 }
}.play()
}
Event Listeners em GroovyFX
> Sintaxe para Closure usando controles embutidos
> Argumentos opcionais para eventos
37
onMouseClicked { MouseEvent e ->
timeline {
at(3.s) { change e.source.radiusProperty() to 0 }
}.play()
}
Sintaxe compacta
{body}
Event Listeners em GroovyFX
> Sintaxe para Closure usando controles embutidos
> Argumentos opcionais para eventos
38
Parametros opcionais para
eventos
{event -> body}
onMouseClicked { MouseEvent e ->
timeline {
at(3.s) { change e.source.radiusProperty() to 0 }
}.play()
}
TableView em Java
39
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 em GroovyFX
40
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 em Java
41
TextField urlField = new TextField(http://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 em GroovyFX
42
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 em GroovyFX
43
Layout em GroovyFX
44
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 em GroovyFX
45
GroovyFX Suporta
46
GroovyFX Suporta
47
48
JavaFX Com Scala
O Que e Scala
> Comecou em 2001 by Martin Odersky
> Compila para bytecodes Java
> Linguagem puramente orientada a objetos
> Tambem para programacao declarativa
2001
Scala Comecou
2003/2004
Scala v1.0
2006
Scala v2.0
2011
Scala 2.9.0 (ultima)
49
Por que Scala?
> Compartilha muitas funcionalidades do JavaFX Script que fazem a
programacao de interfaces mais facil:
Checagem estatica de tipos Encontre seus erros em tempo de
compilacao
Closures Misture os comportamentos e passe-os como referencia
Declarativa Expresse a interface como ela deve aparecer

> Scala tambem suporta Type Safe DSLs!
Conversoes implicitas extensao de classes typesafe
Overloading de operadores com regras de precedencia
DelayedInit / @specialized funcionalides avancadas da linguagem
50
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
})
}
}
}
51
21 Linhas
430 Caracteres
17 Linhas
177 Caracteres
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)
}
}
}
}
52
53
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)
}
}
}
}
Classe base para aplicacoes JavaFX
54
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)
}
}
}
}
Definicao declarativa do Stage
55
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)
}
}
}
}
Definicoes de propriedades
embutidas
56
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)
}
}
}
}
Criacao de sequencias via
Loop
Binding em 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"
57
Animation em 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();
58
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();
Animation em Scala
59
Animacoes JavaFX Script-like
syntax: at (duration) {keyframes}
val timeline = new Timeline {
cycleCount = INDEFINITE
autoReverse = true
keyFrames = for (circle <- circles) yield at (40 s) {
Set(
circle.centerX -> random * stage.width,
circle.centerY -> random * stage.height
)
}
}
timeline.play();
Animation in Scala
60
overloading de operadores para
sintaxe da animacao
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();
Animation in Scala
61
Controle de
velocidade opcional
Event Listeners em Scala
62
> Suportado usando sintaxe Closure embutida
> Argumentos opcionais para tratamento de eventos
> 100% tipagem forte
onMouseClicked = {
Timeline(at(3 s){radius->0}).play()
}
Event Listeners em Scala
> Suportado usando sintaxe Closure embutida
> Argumentos opcionais para tratamento de eventos
> 100% tipagem forte
63
Sintaxe compacta
{body}
onMouseClicked = {
Timeline(at(3 s){radius->0}).play()
}
Event Listeners em Scala
> Suportado usando sintaxe Closure embutida
> Argumentos opcionais para tratamento de eventos
> 100% tipagem forte
64
Evento = parametro opcional
{(event) => body}
onMouseClicked = { (e: MouseEvent) =>
Timeline(at(3 s){radius->0}).play()
}
Sobre o projeto Visage
65
> Metas do projeto Visage:
Compila para JavaFX Java APIs
Envolve toda a linguagem (Annotations, Maps, etc.)
Suporta outros Toolkits

> Venha participar do time!
> Para mais informacoes: http://visage-lang.org/
> Visage e uma domain specific language (DSL) projetada para
suportar a funcao de construcao de interfaces.
E sobre o JavaFX no 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
}
}
}
66
E sobre o JavaFX no 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
}
}
}
67
E sobre o JavaFX no 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
}
}
}
68
Visage e um JavaFX Script++
> Parametros padrao
> Nova sintaxe para:
Angulos 35deg, 4rad, 1turn
Cores #DDCCBB, #AA33AA|CC
Medidas 5px, 2pt, 3in, 4sp
> Checagem de null-reference
var width = rect!.width
> Bindable Maps embutida (Em breve!)
var fruitMap = ["red" : apple, "yellow" : banana]
var fruit = bind fruitMap["red"]
69
Visage e JavaFX 2.0 foram feitos um para o outro
> Binding melhorado
Retem a avaliacao tardia de variaveis com um poder expressivo
adicional
> Colecoes integradas
Sequencias e mapas automaticamente convertidos entre JavaFX
Observable Lists/Maps
> Sintaxe de animacoes embutida
Coloca o JavaFX em um subsistema de animacoes
Prove uma API mais limpa e consistente
70
Conclusao
> Voce pode escrever aplicacoes JavaFX com Java puro
> JavaFX tambem e utilizavel por linguagens alternativas
> Voce pode ter o suporte melhorado utilizando bibliotecas
DSL
GroovyFX
ScalaFX
> Ou uma linguagem de interfaces que roda na JVM
Visage
Pro JavaFX 2 Platform em breve!
> Primeiro trimestre de 2012
> Todos os exemplos reescritos em Java
> Cobre as novas bibliotecas da versao
2.0
> Incluira ScalaFX, GroovyFX e Visage
72
73
Stephen Chin
steveonjava@gmail.com
tweet: @steveonjava

Você também pode gostar