JavaFX & Scene Builder
Ahcène Bounceur
JavaFX
• Bibliothèque Graphique
• Intégrée dans JRE et JDK
• Permet de réaliser des interfaces graphiques évoluées :
– Animations – Effets
– 3D
– Audio
– Vidéo
JavaFX
• JavaFX 1.0 : créée en 2008
– Programmée en Script
• JavaFX 2.0 : 2011
• Programmée en Java
• JavaFX 8.0 : depuis 2014
– Programmée en Java
• Swing et AWT ne seront plus mis à jours
– Mais toujours accessibles – [Branches mortes]
• Utilisez JavaFX
2008 2011 2014
Script Java
JavaFX
8
Premier exemple
• Une classe JavaFX doit hériter de la classe
Application (javafx.application.Application)
• Forcer l’utilisation d’un Thread JavaFX
Premier exemple
import javafx.application.Application;
import javafx.stage.Stage;
public class TestFx extends Application {
@Override
public void start(Stage estrade) { }
}
Premier exemple
import javafx.application.Application;
import javafx.stage.Stage;
public class TestFx extends Application {
@Override
public void start(Stage estrade) { System.out.println("Bonjour");
}
public static void main(String [] args) { launch(args);
}
} public class TestFx {
public static void main(String [] args) { System.out.println("Bonjour");
} }
Stage Scene
Node
L’estrade : Stage
L’estrade : Stage
• javafx.stage.Stage
• Equivalent de Frame (AWT) ou JFrame (Swing)
• Permet de :
– Définir la taille de la fenêtre – Définir le titre de la fenêtre
@Override
public void start(Stage stage) { }
La Scène : Scene
La Scène : Scene
• javafx.scene.Scene
• Décor où l’on placera les différents instruments,
décoration, lumières, etc.
Les nœuds : Node
Les nœuds : Node
• javafx.scene.Node
• Node : instruments, décoration, lumières,
musiciens, comédiens, etc.
Les nœuds : Node
• javafx.scene.Canvas
• javafx.scene.ImageView
• javafx.scene.MediaView
• javafx.scene.Parent
• javafx.scene.Shape
• javafx.scene.Panel
• javafx.scene.Button
• javafx.scene.Label
MA PREMIÈRE FENÊTRE
Ma première fenêtre
import javafx.application.Application;
import javafx.stage.Stage;
public class MonAppli extends Application {
@Override
public void start(Stage estrade) { }
public static void main(String [] args) { launch(args);
} }
MÉTHODE 1 :
PROGRAMMATION DIRECTE
Ma première fenêtre
@Override
public void start(Stage estrade) {
}
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
estrade.setWidth(600);
estrade.setHeight(400);
estrade.show();
}
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
estrade.setWidth(600);
estrade.setHeight(400);
Pane panneau = new Pane();
Button bouton = new Button("Un Bouton");
bouton.setLayoutX(255); bouton.setLayoutY(187);
panneau.getChildren().add(bouton);
estrade.show();
}
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
estrade.setWidth(600);
estrade.setHeight(400);
Pane panneau = new Pane();
Button bouton = new Button("Un Bouton");
bouton.setLayoutX(255); bouton.setLayoutY(187);
panneau.getChildren().add(bouton);
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
estrade.setWidth(600);
estrade.setHeight(400);
Pane panneau = new Pane();
Button bouton = new Button("Un Bouton");
bouton.setLayoutX(255); bouton.setLayoutY(187);
panneau.getChildren().add(bouton);
Scene scene = new Scene(panneau);
// Action du bouton
estrade.setScene(scene);
estrade.show();
}
bouton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) { System.out.println("Hello World!");
} });
Op#on 1 : Lambda Expression Stage
Node
Scene
MÉTHODE 2 : SCENE BUILDER (ACTION PAR LAMBDA
EXPRESSION)
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
estrade.setWidth(600);
estrade.setHeight(400);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Scene Builder
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Scene Builder
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Button bouton = (Button) panneau.getChildren().get(0) ;
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Scene Builder
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Button bouton = (Button) panneau.getChildren().get(0) ; // Action du bouton
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Scene Builder
bouton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) { System.out.println("Hello World!");
} });
Op#on 1 : Lambda Expression
Ma première fenêtre
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<Pane
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button layoutX="255.0" layoutY="187.0" mnemonicParsing="false" text="Mon Button" />
</children>
</Pane>
Scene Builder
panneau.
getChildren
().get(0) ; estrade.setWidth
(600);
estrade.setHeight
(400);
fenetre.fxml
bouton.setLayoutX
(255); bouton.setLayoutY
(187);
MÉTHODE 3 : SCENE BUILDER
(ACTION PAR RÉFÉRENCEMENT
DE MÉTHODE)
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Button bouton = (Button) panneau.getChildren().get(0) ; bouton.setOnAction(this::afficher);
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
@FXML
private void afficher(ActionEvent event) { System.out.println("Bonjour");
}
Scene Builder
MÉTHODE 4 : SCENE BUILDER
(MVC)
Ma première fenêtre
@Override
public void start(Stage estrade) {
estrade.setTitle("Ma première fenêtre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MonAppli.class.getResource("fenetre.fxml"));
Pane panneau = (Pane) loader.load();
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
Scene Builder
M
Ma première fenêtre
public class MonControleur {
@FXML
private void afficher(ActionEvent event) { System.out.println("Bonjour");
} }
Scene Builder
C
Ma première fenêtre
public class MonControleur implements Initializable {
@FXML
private void afficher(ActionEvent event) { System.out.println("Bonjour");
}
@Override
public void initialize(URL location, ResourceBundle resources) { }
}
C
Ma première fenêtre
public class MonControleur implements Initializable {
@FXML
private ComboBox<String> comboBox;
@Override
public void initialize(URL location, ResourceBundle resources) { comboBox.getItems().removeAll(comboBox.getItems());
comboBox.getItems().addAll("A", "B", "C");
comboBox.getSelectionModel().select("A");
} }
C
Ini0a liser un Co mboBo x
Ma première fenêtre
public class MonControleur implements Initializable {
@FXML
private StackPane pane;
@Override
public void initialize(URL location, ResourceBundle resources) { SwingNode sn = new SwingNode();
JButton bouton = new JButton("OK");
sn.setContent(bouton);
pane.getChildren().add(sn);
}
}
Ini0a liser un N œud Swin C
g
Ma première fenêtre Scene Builder
V
1
2
SCENE BUILDER : EXEMPLE
1. Création du projet Java
• Créer un projet JavaFx
• Nommer la classe principale Somme.java
public class Somme extends Application {
@Override
public void start(Stage estrade) throws IOException { estrade.setTitle("Somme");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Somme.class.getResource("exemple.fxml"));
BorderPane panneau = (BorderPane) loader.load();
Scene scene = new Scene(panneau);
estrade.setScene(scene);
estrade.show();
}
public static void main(String[] args) { launch(args);
} }
2. Dessiner votre IHM J
2. Dessiner votre IHM J
3. Affecter les IDs
• Affecter les IDs à tous les composants qui seront utilisés dans votre programme
• Dans l’exemple :
– Champ A (TextField : aTextField)
• Pour récupérer la valeur de A
– Champ B (TextField : bTextFiel)
• Pour récupérer la valeur de B
– Label Somme (Label : sommeLabel)
• Pour afficher la somme de A+B
3. Affecter les IDs
4. Créer le contrôleur
public class SommeControleur {
@FXML
private TextField aTextField;
@FXML
private TextField bTextField;
@FXML
private Label sommeLabel;
@FXML
private void somme() {
int x = Integer.parseInt(aTextField.getText());
int y = Integer.parseInt(bTextField.getText());
int z = x + y ;
sommeLabel.setText("Somme = "+z);
} }
5. Affecter le contrôleur à l’IHM
6. Affecter les actions des boutons
7. Sauvegardez, Rafraichissez &
Exécutez
SCENE BUILDER :
L’INTERFACE
1. Menu
2. IHM (résultat) - View 5. Composants graphiques
3. Hiérarchie & Contrôleur
4. Propriétés Layout et Code
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
1. Le Menu
2. IHM (Résultat)
2. IHM (Résultat)
3.1 La hiérarchie
3.2 Le contrôleur (lien)
4.1. Les propriétés
• Text :
– Font
– Couleur
– Saut de ligne
– Alignement
– Affichage (…)
– Soulignement
– Interlignes
4.1. Les propriétés
• Des propriétés spécifiques peuvent apparaître différemment selon le composant sélectionné
– Exemple : un bouton marqué différemment des autres
(Default Button) …
4.1. Les propriétés
Content Display
Content Text Gap Gap
4.1. Les propriétés
Alignement Ac:va:on Opacité Visibilité Focus Curseur
Effets (ombre, reflets, flous, etc.)
4.1. Les propriétés
• JavaFX CSS permet de personnaliser les
composants graphiques
4.1. Les propriétés
• Soit en utilisant un fichier style CSS (partie Style
Class, …)
4.1. Les propriétés
• Soit en utilisant les styles intégrés (Style)
4.1. Les propriétés
• Soit en utilisant les styles intégrés (Style)
– Cas d’un Label (sans style) :
– Avec un style :
4.1. Les propriétés
• Soit en utilisant les styles intégrés (Style)
– Avec un style :
4.1. Les propriétés
-fx-font-size
4.1. Les propriétés
• Extras :
4.2 Le Layout
• Alignment
• Margin
• Padding
• Spacing
• Vgap
• Hgap
4.2 Le Layout
• Alignment
– Tous les objets du layout seront alignés soit de
gauche à droit, soit de droite à gauche, soit au centre
4.2 Le Layout
• Margin
– Concerne les marges externes du composant
Margin du bouton (dans un HBox)
Margin du bouton (dans un HBox)
4.2 Le Layout
• Padding
– Concerne les marges internes du composant
Padding du bouton
4.2 Le Layout
• Margin & Padding
Margin Padding
Hbox (layout)
4.2 Le Layout
• Dimensions :
– Largeur (Pref Width)
– Longueur (Pref Height)
4.2 Le Layout
• Position du composant dans son layout
158
79
4.2 Le Layout
• Transformation : Il est possible modifier la
rotation (tourner) d’un composant en 2D et en 3D
Degrés
Propor8on Zoom
Transla8on
4.2 Le Layout
4.3 Code
1. U8lisez le même nom des IDs dans le contrôleur !
2. De préférence, meHez tous les noms dans le contrôleurs, ensuite les choisir dans Scene Builder
public class SommeControleur {
@FXML
private TextField aTextField;
@FXML
private TextField bTextField;
@FXML
private Label sommeLabel;
}
4.3 Code
• Des parties peuvent s’afficher spécifiquement pour chaque composants
– Main (OnAction) pour le cas d’un bouton
– Edit et Closing pour le cas d’un TabedPane
– …
4.3 Code
Le Drag & Drop
4.3 Code
@FXML
private void afficher(KeyEvent evt) { System.out.print(evt.getText());
}
4.3 Code
@FXML
private void afficher(MouseEvent evt) {
System.out.println(evt.getX()+" "+evt.getY());
}
4.3 Code
5. Les composants graphiques
5. Les composants graphiques
• Label
5. Les composants graphiques
• Pane, StackPane, BorderPane, AnchorPane,
GridPane
5. Les composants graphiques
• TextField
5. Les composants graphiques
• ProgressBar
5. Les composants graphiques
• SplitPane
– Divider Position : de 0 à 1 (%)
5. Les composants graphiques
• ComboBox/ListBox : initialisation
public class MonControleur implements Initializable {
@FXML
private ComboBox<String> comboBox;
@Override
public void initialize(URL location, ResourceBundle resources) { comboBox.getItems().removeAll(comboBox.getItems());
comboBox.getItems().addAll("A", "B", "C");
comboBox.getSelectionModel().select("A");
} }
5. Les composants graphiques
• ComboBox/ListBox : initialisation
public class MonControleur implements Initializable {
@FXML
private ComboBox<ObjectModel> comboBox;
@Override
public void initialize(URL location, ResourceBundle resources) { comboBox.getItems().removeAll(comboBox.getItems());
comboBox.getItems().addAll("A", "B", "C");
comboBox.getSelectionModel().select("A");
} }
Menus
• Menu
• Sous menu
• Séparateur
• Menu (radio et radio group)
• Raccourcis
COMPLÉMENT
Boites de dialogue
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Information");
alert.setHeaderText("Portes");
alert.setContentText("Verrouillage enfant activé!");
alert.showAndWait();
A par:r de JDK 8u40
Boites de dialogue
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Information");
alert.setHeaderText(null);
alert.setContentText("Verrouillage enfant activé!");
alert.showAndWait();
Boites de dialogue
Alert alert = new Alert(AlertType.WARNING);
Alert alert = new Alert(AlertType.ERROR);
Boites de dialogue
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
} else {
}
Boites de dialogue
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog with Custom Actions");
alert.setHeaderText("Look, a Confirmation Dialog with Custom Actions");
alert.setContentText("Choose your option.");
ButtonType buttonTypeOne = new ButtonType("One");
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne){
// ... user chose "One"
} else if (result.get() == buttonTypeTwo) { // ... user chose "Two"
} else if (result.get() == buttonTypeThree) { // ... user chose "Three"
} else {
// ... user chose CANCEL or closed the dialog }
Boites de dialogue
TextInputDialog dialog = new TextInputDialog("walter");
dialog.setTitle("Text Input Dialog");
dialog.setHeaderText("Look, a Text Input Dialog");
dialog.setContentText("Please enter your name:");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
System.out.println("Your name: " + result.get());
}
Tâches/Thread
Lancer un thread :
Thread th = new Thread() { @Override
public void run() { ...
} });
th.start();
Tâches/Thread
Lancer un thread :
Platform.runLater(new Runnable() {
@Override
public void run() { ...
}
});
Tâches/Thread
Lancer une tâche :
Task task = new Task<Void>() {
@Override
public Void call() { return null;
} };
new Thread(task).start();
Tâches/Thread
Lancer une tâche :
Task task = new Task<Integer>() {
@Override
public Integer call() { return 0;
} };
new Thread(task).start();
Tâches/Thread
Lancer une tâche :
Task task = new Task<Type>() {
@Override
public Type call() {
updateProgress(Double, Double);
updateProgress(Long, Long);
updateMessage(String);
updateTitle(String);
updateValue(Type);
} };
new Thread(task).start();
Mise à jour d’une propriété
Lancer une tâche :
Task task = new Task<Void>() {
@Override
public Void call() {
for (int i=0; i<=10000; i++) { updateProgress(i, 10000);
}
return null;
} };
progress.progressProperty().bind(task.progressProperty());
new Thread(task).start();
@FXML public
ProgressBar
progress
;
Mise à jour d’une propriété
Lancer une tâche :
Task task = new Task<Void>() {
@Override
public Void call() {
for (int i=0; i<=10000; i++) { updateProgress(i, 10000);
}
return null;
} };
progress.progressProperty().bind(task.progressProperty());
new Thread(task).start();
@FXML public
ProgressBar
progress
;
Fichiers (FileChooser)
Ouvrir un fichier
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open file");
File file = fileChooser.showOpenDialog(stage);
Fichiers (FileChooser)
Ouvrir un fichier avec spécification des extensions :
Stage stage = new Stage();
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open file");
fileChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("JPG", "*.jpg") );
File file = fileChooser.showOpenDialog(stage);
Fichiers (FileChooser)
Ouvrir un fichier avec spécification des extensions :
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open file");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("JPG", "*.jpg"), new FileChooser.ExtensionFilter("PNG", "*.png"), );
File file = fileChooser.showOpenDialog(stage);
Fichiers (FileChooser)
Enregistrer un fichier avec spécification des extensions
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save file");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("JPG", "*.jpg"), new FileChooser.ExtensionFilter("PNG", "*.png"), );
File file = fileChooser.showSaveDialog(stage);
Fichiers (FileChooser)
Choisir un dossier
DirectoryChooser dir = new DirectoryChooser();
dir.setTitle("Dossier");
File file = dir.showDialog(stage);
Ajouter un événement (code)
obj.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) { }
});
Sous fenêtre (modale)
• Faire de même pour la fenêtre principale et :
Stage stage = new Stage();
stage.setTitle("titre");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(SenScriptWindow.class.getResource("nom.fxml"));
BorderPane panneau = (BorderPane) loader.load();
Scene scene = new Scene(panneau);
stage.setScene(scene);
stage.initOwner(stage_principal);
stage.initModality(Modality.APPLICATION_MODAL);
stage.showAndWait();