JavaFX2: una panoramica
di Tiziano Lattisi
un po’ di storia (poca)
F3: Chris Oliver (SeeBeyond), script
JavaOne 2007: lancio di JavaFX
2008: plugin Netbeans e SDK
2009: Oracle annuncia acquisizione di Sun, JavaFX 1.2
2010: Oracle acquisisce Sun, JavaFX 1.3
JavaFX script deprecato, Groovy, JRuby, embedding
web, interoperabilità con Swing...
JavaFX2
la metafora del teatro
stage: il palco
scene: la
rappresentazione
node: gli attori
user: lo spettatore
stage
contenitore top-level di un’applicazione JavaFX
differenziato per piattaforma (browser, desktop,
smartphone, etc)
stage diversi possono contenere la stessa scena
possiede stili (decorated, transparent, etc) e modalità
“può” avere una window proprietaria dello stage
lo stage primario è costruito dalla piattaforma
es. primary stage
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Scene scene = [...]; // costruzione della scena
primaryStage.setTitle("Test");
primaryStage.setScene(scene); // associazione della scena allo stage
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
scene
“contenitore” per gli elementi grafici della UI (nodi)
ha background (fill), dimensioni (width, height), e una
sequenza di nodi (content)
i nodi contenuti rappresentano un albero orientato
node
è la classe astratta degli elementi di una scena
ogni nodo può essere foglia (leaf, nessun figlio) o ramo
(branch, zero o più figli)
leaf: Text, Label, Button, Slider, etc...
branch: Group, AnchorPane, FlowPane, HBox, etc...
solo un nodo non ha parent, tutti gli altri ne hanno
esattamente uno
composizione di una scena
più possibilità:
codice imperativo
fxml
codice dichiarativo
codice imperativo
Group group = new Group();
Slider slider = new Slider();
slider.setMin(0);
slider.setMax(1);
slider.setLayoutX(20);
slider.setLayoutY(20);
Label label = new Label("scorri...");
label.setLayoutX(20);
label.setLayoutY(70);
Button button = new Button("azzera");
button.setLayoutX(20);
button.setLayoutY(120);
group.getChildren().addAll(slider, label, button);
Scene scene = new Scene(group, 300, 275);
primaryStage.setTitle("Imperative");
primaryStage.setScene(scene);
primaryStage.show();
FXML
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("FXML");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
<Group xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2"
layoutX="0.0" layoutY="0.0" scaleX="1.0" scaleY="1.0" >
<children>
<Slider layoutX="20.0" layoutY="20.0" min="0.0" max="1.0"/>
<Label layoutX="20.0" layoutY="70.0" text="scorri..." />
<Button layoutX="20.0" layoutY="120.0" text="azzera" />
</children>
</Group>
JavaFX Scene Builder
codice dichiarativo
Scene scene = SceneBuilder.create().width(300).height(275)
.root(
GroupBuilder.create()
.children(
SliderBuilder.create()
.layoutX(20)
.layoutY(20).min(0).max(100).build(),
LabelBuilder.create()
.layoutX(20)
.layoutY(70).text("scorri...").build(),
ButtonBuilder.create()
.layoutX(20)
.layoutY(120).text("azzera").build()
).build()).build();
primaryStage.setTitle("Declarative");
primaryStage.setScene(scene);
primaryStage.show();
proprietà a cascata
Scene scene = SceneBuilder.create().width(300).height(275)
.root(
GroupBuilder.create()
.children(
SliderBuilder.create()
.layoutY(20).min(0).max(100).build(),
LabelBuilder.create()
.layoutY(70).text("scorri...").build(),
ButtonBuilder.create()
.layoutY(120).text("azzera").build()
).build()).build();
primaryStage.setTitle("Declarative");
primaryStage.setScene(scene);
primaryStage.show();
.layoutX(20)
// .layoutX(20)
// .layoutX(20)
// .layoutX(20)
proprietà e binding
final DoubleProperty doubleProperty = new SimpleDoubleProperty();
// il testo della label è sincronizzato con il valore dello slider (fluent)
label.textProperty().bind(slider.valueProperty().asString().concat(" !"));
// il valore dello slider e la proprietà del bean sono sincronizzati bidirezionalmente
slider.valueProperty().bindBidirectional(doubleProperty);
una Property rappresenta un dato che può essere
messo in bind unidirezionale con un Observable, o
bidirezionale con una Property (extends Observable)
selection binding
fluent interface API
JavaFX Beans convention
oggetto Java con un set di metodi accessori:
getter e setter secondo convenzione Java Bean
un getter nome+”Property” per la proprietà JavaFX
private StringProperty title = new SimpleStringProperty(this, “title”, “”);
public StringProperty titleProperty(){
return title;
}
public final String getTitle(){
return title.get();
}
public final void setTitle(String t){
title.set(t)
}
event handling
button.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent e){
doubleProperty.setValue(0.0);
}
});
è possibile definire EventHandler per eventi di tastiera,
mouse, e drag&drop
sono proprietà dei nodi che iniziano con “on”
FXML hook up
<Group layoutX="0.0" layoutY="0.0" scaleX="1.0" scaleY="1.0" xmlns:fx="http://
javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller">
<children>
<Slider fx:id=”slider” layoutX="20.0" layoutY="20.0" />
<Label layoutX="20.0" layoutY="70.0" text="scorri..." />
<Button layoutX="20.0" layoutY="120.0" text="azzera" onAction=”#handlePush”/>
</children>
</Group>
public class Controller implements Initializable {
@FXML private Slider slider;
@FXML private void handlePush(ActionEvent event) { }
@Override public void initialize(URL url, ResourceBundle rb) { }
}
animazioni
final Timeline timeline = TimelineBuilder.create()
.keyFrames(
new KeyFrame(
new Duration(3000.0),
new KeyValue(slider.valueProperty(), 0.0))
).build();
button.setOnAction(new EventHandler<ActionEvent>(){
@Override public void handle(ActionEvent e){
//doubleProperty.setValue(0.0);
timeline.playFromStart();
}
});
un’istanza di Timeline può definire un’animazione
tramite la configurazione di fotogrammi chiave; lo slider
ritorna gradatamente a zero in 3 secondi
css
è possibile utilizzare fogli di stile per modificare, anche
dinamicamente, l’aspetto della UI
implementando un foglio di stile
/* style.css */
.slider .thumb {
-fx-background-image :url("nyan.png");
-fx-padding: 25;
}
scene.getStylesheets()
.add(getClass().getResource("style.css").toExternalForm());
in-line in un documento FXML
<Slider layoutX="20.0" layoutY="20.0" min="0.0" max="1.0"
style=”-fx-background-image: @nayan.png; -fx-padding: 25”/>
media
è basato su GStreamer (framework multimediale OS)
formati: mp3, aif, wav, fxm, flv
final AudioClip clip = new AudioClip(getClass().getResource("nyan.mp3").toString());
clip.volumeProperty().bindBidirectional(slider.valueProperty());
button.setOnAction(new EventHandler<ActionEvent>(){
@Override public void handle(ActionEvent e){
timeline.playFromStart();
if( clip.isPlaying() ){ clip.stop(); }
clip.play();
}
});
di cosa non abbiamo parlato
embedding:
Swing (JFXPanel)
SWT (FXCanvas)
collections:
ObservableList
ObservableMap
Chart API
concorrenza
altri linguaggi:
Groovy (GroovyFX)
Scala (ScalaFX)
Visage
fine
Thank you.
Tiziano Lattisi
Me: http://www.linkedin.com/in/tizianolattisi/
Slides: http://www.slideshare.net/lattisi/
JavaFX: http://www.oracle.com/technetwork/javafx/

JavaFX2: una panoramica

  • 1.
  • 2.
    un po’ distoria (poca) F3: Chris Oliver (SeeBeyond), script JavaOne 2007: lancio di JavaFX 2008: plugin Netbeans e SDK 2009: Oracle annuncia acquisizione di Sun, JavaFX 1.2 2010: Oracle acquisisce Sun, JavaFX 1.3 JavaFX script deprecato, Groovy, JRuby, embedding web, interoperabilità con Swing... JavaFX2
  • 3.
    la metafora delteatro stage: il palco scene: la rappresentazione node: gli attori user: lo spettatore
  • 4.
    stage contenitore top-level diun’applicazione JavaFX differenziato per piattaforma (browser, desktop, smartphone, etc) stage diversi possono contenere la stessa scena possiede stili (decorated, transparent, etc) e modalità “può” avere una window proprietaria dello stage lo stage primario è costruito dalla piattaforma
  • 5.
    es. primary stage publicclass Main extends Application { @Override public void start(Stage primaryStage) throws Exception{ Scene scene = [...]; // costruzione della scena primaryStage.setTitle("Test"); primaryStage.setScene(scene); // associazione della scena allo stage primaryStage.show(); } public static void main(String[] args) { launch(args); } }
  • 6.
    scene “contenitore” per glielementi grafici della UI (nodi) ha background (fill), dimensioni (width, height), e una sequenza di nodi (content) i nodi contenuti rappresentano un albero orientato
  • 7.
    node è la classeastratta degli elementi di una scena ogni nodo può essere foglia (leaf, nessun figlio) o ramo (branch, zero o più figli) leaf: Text, Label, Button, Slider, etc... branch: Group, AnchorPane, FlowPane, HBox, etc... solo un nodo non ha parent, tutti gli altri ne hanno esattamente uno
  • 8.
    composizione di unascena più possibilità: codice imperativo fxml codice dichiarativo
  • 9.
    codice imperativo Group group= new Group(); Slider slider = new Slider(); slider.setMin(0); slider.setMax(1); slider.setLayoutX(20); slider.setLayoutY(20); Label label = new Label("scorri..."); label.setLayoutX(20); label.setLayoutY(70); Button button = new Button("azzera"); button.setLayoutX(20); button.setLayoutY(120); group.getChildren().addAll(slider, label, button); Scene scene = new Scene(group, 300, 275); primaryStage.setTitle("Imperative"); primaryStage.setScene(scene); primaryStage.show();
  • 10.
    FXML Parent root =FXMLLoader.load(getClass().getResource("sample.fxml")); primaryStage.setTitle("FXML"); primaryStage.setScene(new Scene(root, 300, 275)); primaryStage.show(); <Group xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" layoutX="0.0" layoutY="0.0" scaleX="1.0" scaleY="1.0" > <children> <Slider layoutX="20.0" layoutY="20.0" min="0.0" max="1.0"/> <Label layoutX="20.0" layoutY="70.0" text="scorri..." /> <Button layoutX="20.0" layoutY="120.0" text="azzera" /> </children> </Group>
  • 11.
  • 12.
    codice dichiarativo Scene scene= SceneBuilder.create().width(300).height(275) .root( GroupBuilder.create() .children( SliderBuilder.create() .layoutX(20) .layoutY(20).min(0).max(100).build(), LabelBuilder.create() .layoutX(20) .layoutY(70).text("scorri...").build(), ButtonBuilder.create() .layoutX(20) .layoutY(120).text("azzera").build() ).build()).build(); primaryStage.setTitle("Declarative"); primaryStage.setScene(scene); primaryStage.show();
  • 13.
    proprietà a cascata Scenescene = SceneBuilder.create().width(300).height(275) .root( GroupBuilder.create() .children( SliderBuilder.create() .layoutY(20).min(0).max(100).build(), LabelBuilder.create() .layoutY(70).text("scorri...").build(), ButtonBuilder.create() .layoutY(120).text("azzera").build() ).build()).build(); primaryStage.setTitle("Declarative"); primaryStage.setScene(scene); primaryStage.show(); .layoutX(20) // .layoutX(20) // .layoutX(20) // .layoutX(20)
  • 14.
    proprietà e binding finalDoubleProperty doubleProperty = new SimpleDoubleProperty(); // il testo della label è sincronizzato con il valore dello slider (fluent) label.textProperty().bind(slider.valueProperty().asString().concat(" !")); // il valore dello slider e la proprietà del bean sono sincronizzati bidirezionalmente slider.valueProperty().bindBidirectional(doubleProperty); una Property rappresenta un dato che può essere messo in bind unidirezionale con un Observable, o bidirezionale con una Property (extends Observable) selection binding fluent interface API
  • 15.
    JavaFX Beans convention oggettoJava con un set di metodi accessori: getter e setter secondo convenzione Java Bean un getter nome+”Property” per la proprietà JavaFX private StringProperty title = new SimpleStringProperty(this, “title”, “”); public StringProperty titleProperty(){ return title; } public final String getTitle(){ return title.get(); } public final void setTitle(String t){ title.set(t) }
  • 16.
    event handling button.setOnAction(new EventHandler<ActionEvent>(){ @Override publicvoid handle(ActionEvent e){ doubleProperty.setValue(0.0); } }); è possibile definire EventHandler per eventi di tastiera, mouse, e drag&drop sono proprietà dei nodi che iniziano con “on”
  • 17.
    FXML hook up <GrouplayoutX="0.0" layoutY="0.0" scaleX="1.0" scaleY="1.0" xmlns:fx="http:// javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller"> <children> <Slider fx:id=”slider” layoutX="20.0" layoutY="20.0" /> <Label layoutX="20.0" layoutY="70.0" text="scorri..." /> <Button layoutX="20.0" layoutY="120.0" text="azzera" onAction=”#handlePush”/> </children> </Group> public class Controller implements Initializable { @FXML private Slider slider; @FXML private void handlePush(ActionEvent event) { } @Override public void initialize(URL url, ResourceBundle rb) { } }
  • 18.
    animazioni final Timeline timeline= TimelineBuilder.create() .keyFrames( new KeyFrame( new Duration(3000.0), new KeyValue(slider.valueProperty(), 0.0)) ).build(); button.setOnAction(new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent e){ //doubleProperty.setValue(0.0); timeline.playFromStart(); } }); un’istanza di Timeline può definire un’animazione tramite la configurazione di fotogrammi chiave; lo slider ritorna gradatamente a zero in 3 secondi
  • 19.
    css è possibile utilizzarefogli di stile per modificare, anche dinamicamente, l’aspetto della UI implementando un foglio di stile /* style.css */ .slider .thumb { -fx-background-image :url("nyan.png"); -fx-padding: 25; } scene.getStylesheets() .add(getClass().getResource("style.css").toExternalForm()); in-line in un documento FXML <Slider layoutX="20.0" layoutY="20.0" min="0.0" max="1.0" style=”-fx-background-image: @nayan.png; -fx-padding: 25”/>
  • 20.
    media è basato suGStreamer (framework multimediale OS) formati: mp3, aif, wav, fxm, flv final AudioClip clip = new AudioClip(getClass().getResource("nyan.mp3").toString()); clip.volumeProperty().bindBidirectional(slider.valueProperty()); button.setOnAction(new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent e){ timeline.playFromStart(); if( clip.isPlaying() ){ clip.stop(); } clip.play(); } });
  • 21.
    di cosa nonabbiamo parlato embedding: Swing (JFXPanel) SWT (FXCanvas) collections: ObservableList ObservableMap Chart API concorrenza altri linguaggi: Groovy (GroovyFX) Scala (ScalaFX) Visage
  • 22.
    fine Thank you. Tiziano Lattisi Me:http://www.linkedin.com/in/tizianolattisi/ Slides: http://www.slideshare.net/lattisi/ JavaFX: http://www.oracle.com/technetwork/javafx/