Date post: | 06-Jun-2015 |
Category: |
Technology |
Upload: | tiziano-lattisi |
View: | 347 times |
Download: | 4 times |
JavaFX2: una panoramicadi 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
stagecontenitore 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 stagepublic 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 imperativoGroup 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 dichiarativoScene 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 cascataScene 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 bidirezionalmenteslider.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 conventionoggetto 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 parlatoembedding:
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/