# Programmation JavaFX/Version imprimable

* Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
* Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
* Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.
Une version à jour et éditable de ce livre est disponible sur Wikilivres, une bibliothèque de livres pédagogiques, à l'URL : https://fr.wikibooks.org/wiki/Programmation_JavaFX

# Introduction

JavaFX est un framework et une bibliothèque d'interface utilisateur issue du projet OpenJFX, qui permet aux développeurs Java de créer une interface graphique pour des applications de bureau, des applications internet riches et des applications smartphones et tablettes tactiles. Il permet également le rendu de scènes 3D.
JavaFX a été conçu initialement pour remplacer Swing et AWT à long terme.

## Utilisation
### Java 7 à 10

Le framework JavaFX est intégré aux versions 7 à 10 du JDK et du JRE (librairie jfxrt.jar). Il n'y a donc aucun logiciel supplémentaire à installer.
Des applications de démonstration sont fournies avec le JDK dans un sous-répertoire
Lancez en particulier l'application Ensemble8.jar qui donne un large aperçu de toutes les possibilités de JavaFX. Le code source de chaque démonstration est composé souvent d'un seul fichier, disponible par simple clic sur le lien "View source" associé à la démo.

### Java 11

À partir de Java 11, JavaFX (version 11 également) est un module indépendant à installer séparément depuis le site suivant :
    https://openjfx.io/

## Les packages de JavaFX

Le framework JavaFX est composé de classes situées dans les packages commençant par javafx :

### javafx.application

    Les classes pour la gestion de l'application JavaFX.

### javafx.stage

    Les classes pour la gestion des fenêtres applicatives (Stage).

### javafx.scene

    Les classes pour la gestion des scènes qui définissent le contenu des fenêtres. Ce contenu est constitués de nœuds (classe Node).

   ### javafx.scene.control

       Composants d'interface utilisateur : boutons, bouton radio, case à cocher, champ de texte, ...

   ### javafx.scene.layout

       Gestion de la taille et du positionnement des nœuds composant un scène.

   ### javafx.scene.shape

       Formes de base en 2D et 3D : rectangle, cercle, courbe, chemin, polygone, sphère, boîte, cylindre, ...

   ### javafx.scene.paint

       Couleur et autres objets tels que les dégradés (radial, linéaire, ...) pour le remplissage et le traçage des formes et du texte.

   ### javafx.scene.image

       Classes pour le chargement et l'affichage des images.

   ### javafx.scene.text

       Classes pour l'affichage du texte, gestion des polices de caractères.

   ### javafx.scene.transform

       Transformation 2D et 3D des nœuds : translation, rotation, échelle, étirage. Ces transformations sont aussi accessibles par appel de méthode sur les nœuds.

   ### javafx.scene.input

       Gestion des interactions avec l'utilisateur par le clavier et la souris.

   ### javafx.scene.effect

       Effets graphiques par application de filtres.

   ### javafx.scene.effect.light
   ### javafx.scene.chart

       Création et gestion de graphiques : courbe de points, graphique à barres, camembert, ...

   ### javafx.scene.chart.data

       Gestion des données pour les graphiques.

   ### javafx.scene.chart.part
### javafx.geometry

    Les classes de gestion des dimensions et positions des nœuds (éléments d'une scène) en 2D et 3D.

### javafx.ext.swing

    Adaptateurs pour encapsuler des composants Swing dans une scène. Ces classes sont en général utilisées pour effectuer une transition des composants Swing vers leur équivalents JavaFX.

## Utilisation avec Eclipse

Après la création d'un nouveau projet Eclipse ou l'import d'un projet existant utilisant un package de JavaFX, il est possible que Eclipse affiche des messages d'erreurs de ce type :
Dans ce cas, il faut ajouter une règle d'accès dans le "Build Path" du projet :
* Cliquer avec le bouton droit sur le projet, "Build Path" > "Configure Build Path...".
* Dans l'onglet "Libraries", déplier le nœud "JRE System Library".
* Cliquer "Access rules", puis le bouton "Edit..." situé à droite.
* Dans la nouvelle fenêtre, cliquer le bouton "Add..." situé à droite.
* Mettre "Accessible" comme valeur pour "Resolution".
* Entrer "javafx/**" comme valeur pour "Rule Pattern".
* Valider toutes les fenêtres de dialogues ouvertes.
Le chapitre suivant décrits les objets composant une application JavaFX.

## Réferences

* ↑ https://www.infoworld.com/article/3305073/removed-from-jdk-11-javafx-11-arrives-as-a-standalone-module.html

# Composants d'une application

Ce chapitre est important car il présente les classes de bases communes aux applications JavaFX. Un exemple illustre ce chapitre, complété au fur et à mesure des notions introduites dans les sections du chapitre.

## Application

Application est le nom de la classe Abstraite à implémenter par la sous-classe représentant l'application JavaFX.
Cette sous-classe ne comporte pas obligatoirement une méthode statique main car la JVM peut lancer directement un JAR contenant une application JavaFX en utilisant certains attributs particuliers du fichier de manifeste.
Elle suit un cycle particulier :
* La méthode statique launch(Class c, String args) est appelée soit par une méthode main(String args), soit directement par la JVM. Le premier argument est la classe implémentant la classe abstraite Application et peut être omis, auquel cas la méthode utilise la classe à partir de laquelle elle a été appelée. Le second argument est un tableau des arguments de la ligne de commande (voir section « Récupération des arguments de la ligne de commande » ci-dessous).
* Cette méthode initialise l'environnement JavaFX et appelle ensuite la méthode init.
* La méthode start(Stage stage) est ensuite appelée pour démarrer l'application : créer l'interface et les scènes à afficher dans la fenêtre (stage) donnée en argument. La sous-classe de Application doit implémenter cette méthode.
* La méthode stop est appelée pour arrêter l'application, généralement quand la fenêtre de l'application est fermée. L'implémentation par défaut ne fait rien.

### Récupération des arguments de la ligne de commande

Quel que soit le mode de lancement de l'application, la méthode getParameters de la classe Application retourne un objet de classe Parameters :
Les méthodes de la classe Parameters permettent de récupérer les arguments de la ligne de commande :

#### List<String> getRaw

    Cette méthode retourne une liste contenant tous les arguments de la ligne de commande.

#### Map<String,String> getNamed

    Cette méthode retourne un dictionnaire de tous les arguments nommés de la forme suivante :
    --name=value

#### List<String> getUnnamed

    Cette méthode retourne une liste contenant les autres arguments (non nommés) de la ligne de commande.

### Exemple
## Stage

Une instance de la classe Stage représente une fenêtre d'application JavaFX.
Les principales méthodes sont les suivantes:

### setTitle(String title)

    Définir le titre de la fenêtre.

### setScene(Scene scene)

    Définir la scène à afficher.

### show

    Afficher la fenêtre.
Il est également possible d'ajouter une ou plusieurs icônes en modifiant la liste observable retournée par la méthode getIcons.

## Liste observable

Une liste observable est une liste générique dont les modifications sont notifiés aux instances des classes implémentant l'interface ListChangeListener enregistrées sur la liste par la méthode addListener. Les listes observables sont très utilisées dans l'API JavaFX.

## Scene

Une scène est composée de nœuds (Node). Une scène comporte des nœuds 2D (composants : boutons, labels...) ou 3D (formes : sphères, boîtes, cylindres...).

## Classes similaires à AWT et Swing

JavaFX a été conçu pour remplacer Swing et AWT à long terme. Le framework est donc indépendant et possède des classes spécifiques, nommées comme celles de Swing et AWT et jouant à peu près le même rôle mais sont différentes. Ce qui veut dire qu'il n'est pas possible d'utiliser directement les classes de JavaFX en Swing/AWT et vice-versa.
La spécificité des classes de JavaFX permet leur utilisation en 2D et en 3D.

### Color

    Représente une couleur, modélisée par les composantes RVB (Rouge, Vert, Bleu) dont les valeurs sont de type double et comprises entre 0.0 et 1.0.

### Image

    Représente une image.

## Nœud (Node)

Un nœud représenté un élément affichable dans une scène.
Certaines classes d'objet ne sont pas des nœuds ; leurs instances doivent alors être encapsulées dans une vue (View) gérant le type d'objet :
* ImageView pour les objets de classe Image ;
* MeshView pour les objets de classe Mesh (notamment la sous-classe TriangleMesh) ;

### Exemple : afficher une image
# Classes 2D
## Hiérarchie des classes 2D

La hiérarchie de classes ci-dessous montrent les classes communes aux application 2D et 3D, vues précédemment et les classes spécifiques à la 2D.

## Classes de base

La classe de base des composants JavaFX est Node. Il s'agit de la classe utilisée pour l'ajout de nœuds dans les conteneurs (par exemple Pane).
Parmi les sous-classes, il y a la classe Parent servant de base à tous les composants pouvant contenir d'autres composants (nœuds enfants dans l'arbre). Il y a également la sous-classe MediaViewer héritant directement de la classe Node, ce qui signifie que ce composant ne peut pas contenir d'autres composants, et aussi qu'il peut être ajouté à n'importe quel composant Parent. Voir le chapitre Jouer une vidéo ou un son pour une utilisation concrète de la classe MediaViewer.
La classe Region est la classe de base des composants de type Pane et définit une composition similaire à celle du modèle de boîte en CSS :
marge extérieure (Margin)
bordure (Border)
espace intérieur (Padding)
aire intérieure (ContentArea)
La similitude avec le modèle de boîte en CSS est due au fait que les composants JavaFX peuvent être stylisés avec des règles CSS (voir le livre Le langage CSS).

## Styles CSS sur les composants JavaFX

Les composants JavaFX dérivant de la classe Node peuvent être stylisés en CSS. Cependant, les styles CSS supportés sont limités, car basés sur W3C CSS version 2.1 avec quelques ajouts spécifiques à JavaFX. De plus les propriétés doivent être préfixées par -fx-.
Exemple de code :

## Sources

* ↑ JavaFX Region - https://jenkov.com/tutorials/javafx/region.html
* ↑ JavaFX CSS Reference Guide - https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html

# Formes 3D

Une scène en 3D est composée de formes 3D, de source lumineuses et d'une caméra définissant le point de vue de la scène.

## Coordonnées et orientation des axes 3D

Les coordonnées d'un point ou d'une forme est un ensemble de 3 valeurs de type double, nommées X, Y et Z.
L'orientation par défaut des axes est le suivant :
* L'axe X est orienté de la gauche vers la droite : une valeur plus élevée de X donne une position relative plus à droite.
* L'axe Y est orienté du haut vers le bas.
* L'axe Z est orienté du plus proche au plus loin.

## Classe de base

La classe Shape3D est la classe de base des formes 3D. Elle définit les méthodes communes à toutes les formes, permettant de les placer/déplacer et de les orienter.
La position initiale à la création d'une forme 3D est (0,0,0).

### setTranslateX(double)

    Incrémente la coordonnée X du nœud.

### setTranslateY(double)

    Incrémente la coordonnée Y du nœud.

### setTranslateZ(double)

    Incrémente la coordonnée Z du nœud.
La classe Shape3D a 4 implémentations concrètes :
* La classe Sphere
* La classe Cylinder
* La classe Box représente une boîte ou parallélépipède rectangle ou pavé droit.
* La classe MeshView permet de définir une forme particulière à partir d'une instance de la classe abstraite Mesh. La classe abstraite Mesh possède la sous-classe TriangleMesh comme implémentation concrète, définissant la forme à partir de triangles.
Les sous-classes présentées ci-dessous ont des caractéristiques communes :
* Par défaut, les formes sont centrées sur le point d'origine (0,0,0).
* Si les dimensions ne sont pas spécifiées (constructeur sans arguments), les dimensions par défaut sont définies par une boîte 2x2x2.

## Sphère (classe Sphere)

Les paramètres définissant une sphère sont les suivants (même ordre que les constructeurs de la classe) :

### double radius

    (Optionnel) Rayon de la sphère. La valeur par défaut est 1.0.

### int divisions

    (Optionnel) Nombre de divisions de la circonférence. La valeur par défaut est 64.

### Exemple
## Cylindre (classe Cylinder)

Les paramètres définissant un cylindre sont les suivants (même ordre que les constructeurs de la classe) :

### double radius

    (Optionnel) Rayon du cylindre. La valeur par défaut est 1.0.

### double height

    (Optionnel) Hauteur du cylindre. La valeur par défaut est 2.0.

### int divisions

    (Optionnel) Nombre de divisions de la circonférence. La valeur par défaut est 64.
L'orientation initiale du cylindre suit l'axe Y ; les faces circulaires sont donc perpendiculaire à l'axe Y.

### Exemple
## Boîte (classe Box)

Les paramètres définissant une boîte sont les suivants (même ordre que les constructeurs de la classe) :

### double width

    (Optionnel) Largeur de la boîte (axe X). La valeur par défaut est 2.0.

### double height

    (Optionnel) Hauteur de la boîte (axe Y). La valeur par défaut est 2.0.

### double depth

    (Optionnel) Profondeur de la boîte (axe Z). La valeur par défaut est 2.0.

### Exemple
## Forme triangulée

Une forme triangulée est définie avec un objet de class TriangleMesh. Le seul constructeur à appeler n'a aucun paramètres. Il faut ensuite remplir les listes de points, de faces triangulaires et les points de texture.
Méthodes de la classe TriangleMesh:

### getTexCoords

    Retourne la liste modifiable (float) des points (U,V) pour les textures.

### getPoints

    Retourne la liste modifiable (float) de tous les sommets.

### getFaces

    Retourne la liste modifiable (int) des index des sommets de chaque face.

### getFaceSmoothingGroups

    Retourne la liste modifiable (int) des identifiants de face. La même valeur signifiant qu'il s'agit de la même face. Ceci est utilisé pour le rendu continu des faces.

### Exemple

Il faut ensuite encapsuler la triangulation dans une forme :

## Sources de lumière

Par défaut, la scène n'a aucune source lumineuse. Le rendu serait donc de la couleur de fond de la scène.
Une source lumineuse a une couleur filtrant celle des objets, une intensité, et une position.
JavaFX a deux types de sources lumineuses :

### Lumière ambiante (AmbientLight)

    Une source lumineuse sans position, se diffusant sur toute la scène avec la même intensité.

### Lumière ponctuelle (PointLight)

    Une source lumineuse avec position, dont la luminosité décroit avec l'augmentation de la distance.
Il faut également définir pour chaque source lumineuse, la liste des objets éclairés par celle-ci.

### Exemple
## Caméra

La caméra (classe Camera) représente le point de vue d'affichage de la scène : position et orientation. Pour une représentation en 3D, la sous-classe PerspectiveCamera est utilisée.

### setNearClip(float)

    Définit la distance minimale pour le rendu des objets.

### setFarClip(float)

    Définit la distance maximale pour le rendu des objets.

### getTransforms

    Liste modifiable des transformations (translation, rotation).

## Construction de la scène

La scène est construite en spécifiant le nœud racine regroupant les éléments de la scène.

### Exemple

Il ne manque que la scène constituée des éléments vus précédemment.

## Code complet

L'apparence des objets sera améliorée dans le chapitre suivant.

# Apparence 3D

L'apparence par défaut des objets de la scène construite au chapitre précédent est plutôt monotone :
Le but de ce chapitre est de montrer comment améliorer l'apparence des objets en leur donnant une couleur ou une texture.
L'apparence d'un objet (couleur, reflets, texture, ...) est défini par une instance de la classe abstraite Material. JavaFX fournit une classe concrète nommée PhongMaterial, nommée d'après le modèle d'ombrage de Phong.

## Couleur

Les méthodes de la classe PhongMaterial sont les suivantes :

### setDiffuseColor(Color)

    Définit la couleur principale.

### setSpecularColor(Color)

    Définit la couleur des reflets des sources lumineuses.

### setSpecularPower(float)

    Définit la puissance de réflexion.

### Exemple

On peut ensuite assigner l'apparence aux objets :

## Texture

Une texture est définie par une image pouvant définir la couleur de diffusion, de réflexion, d'illumination de l'objet.
Les méthodes de la classe PhongMaterial concernant les textures sont les suivantes :

### setDiffuseMap(Image)

    Définit la texture pour la couleur de diffusion.

### setSpecularMap(Image)

    Définit la texture pour la couleur de reflet.

### setSelfIlluminationMap(Image)

    Définit la texture pour l'intensité d'illumination.

### setBumpMap(Image)

    Définit la texture pour la granularité de l'objet.

### Exemple

L'exemple ci-dessous utilise l'image Red-brick-wall-texture-1.jpg disponible sur commons.

## Ajustements

La texture de la base carrée fait apparaître les deux triangles car les 2 faces adjacentes sont associées à deux triangles qui ne sont pas adjacent dans la texture :
En ajustant la texture comme dans le code ci-dessous, on obtient une texture uniforme pour la base carrée :
Dans cette version, la caméra est fixe. Le chapitre suivant résout le problème en ajoutant la possibilité d'interagir avec la souris pour déplacer la caméra.

# Interactions 3D

Ce chapitre explique comment ajouter de l'interaction à une scène 3D.
Le principe est le même avec les composants 2D d'une interface graphique : ajouter un listener à notifier de certains évènements.

## Rotations et déplacements

Le code des exemples précédents contient déjà les transformations appliquées à la caméra :
Il suffit d'ajouter des listeners pour modifier les paramètres de ces transformations selon les déplacements de la souris quand le bouton gauche est maintenu appuyé. La modification dépend des touches Shift et Ctrl appuyées lors du déplacement de la souris :
* Si la touche Ctrl est appuyée; la caméra est déplacée dans le plan XY ;
* Si la touche Shift est appuyée; la caméra est déplacée dans le plan ZY ;
* Sinon, l'angle de rotation autour de l'axe horizontal est contrôlé par les mouvements verticaux de la souris et vice-versa.
Les listeners sont ajoutés à la scène.
La rotation est centrée sur la sphère, c'est à dire en (0,0,0), quel que soit la position de la caméra car il s'agit des deux premières transformations ajoutées à la caméra, avant le déplacement :

## Code complet
# Jouer une vidéo ou un son

JavaFX permet de jouer une vidéo ou un son en utilisant les classes du package javafx.scene.media.

## Jouer un fichier

Le code d'exemple ci-dessous montre comment jouer une vidéo ou un son à partir d'un fichier.
* Si le fichier est une vidéo, elle est affichée dans la scène. Initialement en mode plein écran, la taille de la vidéo s'adapte à celle de la scène par binding des propriétés width et height.
* Si le fichier est un son, le son est audible et la scène affiche la couleur de fond.
Comme le fichier est joué de manière asynchrone en tâche de fond, la référence au MediaPlayer doit être conservée pour que le garbage collector ne supprime pas le media player, sinon cela provoquerait un arrêt du fichier au bout d'un moment aléatoire. Dans le code précédent, la référence au MediaPlayer est conservée par l'objet viewer. Il est possible de se passer d'objet viewer (instance de la classe MediaView), pour jouer le son seulement, auquel cas il faut conserver la référence au MediaPlayer dans la classe.

# Scene Builder

Scene Builder est un outil interactif de conception d'interface graphique pour JavaFX. Il permet de créer des interfaces utilisateurs rapidement et sans avoir besoin de coder ; il en résulte des fichiers au format FXML qui sont ensuite chargés par le programme pour afficher une interface graphique à l'utilisateur.
Développé initialement par Oracle et sous le nom JavaFX Scene Builder, son code source a été publié en open source à partir de sa version 2.0.
Depuis, le logiciel est principalement développé et soutenu par la société Gluon.

## Utilisation

Le logiciel s'utilise avec la technique du glisser/déposer : un panneau latéral situé à gauche de la fenêtre permet à l'utilisateur de sélectionner et positionner un composant dans la hiérarchie des composants ou sur la vue centrale affichant le rendu.
Un panneau latéral positionné à droite de la fenêtre permet quant à lui de définir les caractéristiques du composant sélectionné par l'utilisateur.
Les interfaces sont enregistrées dans des fichiers au format FXML, qui sont ensuite lus et chargés en mémoire par le programme, puis affichés à l'écran.

## FXML

FXML est un format de données textuel, dérivé du format XML, qui permet de décrire une interface utilisateur pour des applications conçues avec JavaFX.
Il s'agit d'une alternative à la conception d'interfaces réalisée par l'écriture de lignes de codes, en découplant l'interface graphique du code source qui le contrôle.
Cette technologie a été intégrée dans JavaFX à partir de sa version 2.0, pour remplacer JavaFX Script.