Mis à jour le 05/10/2017
  • 4 heures
  • Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

La scène graphique de JavaFX

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Dans ce chapitre, on va mettre les mains dans le cambouis ;) . Dans un premier temps on va découvrir le principe de la programmation en JavaFX, je décrirais notamment le fonctionnement de la scène graphique. Puis dans un deuxième temps on va analyser le code qu'on a compilé au chapitre 2 sans avoir essayé de le comprendre.

J'espère qu'à la fin de ce chapitre vous aurez compris comment est structuré le code d'une application JavaFX, vous verrez c'est très simple (une fois qu'on a compris bien sûr). Il y a beaucoup de points communs avec une application Java classique.

Présentation de la scène graphique

Imaginons que vous voulez monter une pièce de théâtre, avec des acteurs, une histoire, des spectateurs, etc...

  • 1. La première chose dont vous devez disposer est un théâtre, sans cela vous ne pourrez pas jouer la pièce, personne ne pourrait la voir et ça n'aurait aucun intérêt :(.

  • 2. Dans ce théâtre, il faudra créer une scène sur laquelle toute votre histoire se déroulera, quelques planches de bois un peu surélevées au centre du théâtre pour que tout le monde voit le déroulement de la pièce...

  • 3. Et sur cette scène, vous devrez intégrer différents acteurs auxquels vous aurez attribué un texte, un costume et un certain comportement lorsqu'ils se trouvent sur la scène.

Une application JavaFX est un peu constituée comme une scène de théâtre.

  • 1. Le premier élément dont elle est constituée est un objet Stage, c'est l'équivalent de notre théâtre de tout à l'heure, c'est dans cet objet que tout se passe, il représente la fenêtre de notre application.

  • 2. A l'intérieur de cet objet Stage il y a un objet Scene, l'équivalent de la scène du théâtre. Tout ce qui apparaitra dans notre application devra y être inséré.

  • 3. Enfin, l'objet Scene contient des nœuds graphiques, l'équivalent des acteurs de notre pièce de théâtre. Ces nœuds graphiques sont des objets qui peuvent être de différents types : des cercles, des rectangles, des images... Ils peuvent même être des groupes de plusieurs objets graphiques.

Ce schéma représente la structure d'une application JavaFX :

Image utilisateur

On voit que l'objet Scene contient un groupe root. C'est le groupe racine qui contiendra tous les autres objets et groupes d'objets graphiques. Un objet Scene ne contient qu'un seul groupe root.

A partir de ce groupe root, on peut insérer et retirer tous les nœuds graphiques que l'on souhaite. Comme je l'ai dit, un nœud graphique peut être :

  • Un objet graphique comme un cercle, un rectangle, une image, etc.

  • Un groupe contenant des objets graphiques, un groupe peut même contenir d'autres groupes.

  • Ou un type d'objet graphique que nous avons nous-même définit. Nous verrons dans le chapitre 6 comment créer nos propres types d'objets graphiques grâce aux classes.

Vous voyez que le principe est assez simple à comprendre :) . Voyons maintenant le code qui correspond à tout ça. Pour cela, analysons le projet que nous avons créé et compilé au chapitre 2.

Le code JavaFX

Si vous avez bien suivi les chapitres précédents, vous devriez avoir créé un projet Test qui ne contient pour l'instant qu'un package test et une feuille de code Test.java.

Voici le code que devrait contenir la feuille Test.java de notre projet :

package test;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Test extends Application {

    public static void main(String[] args) {
        Application.launch(Test.class, args);
    }
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World");
        Group root = new Group();
        Scene scene = new Scene(root, 300, 250, Color.LIGHTGREEN);
        Button btn = new Button();
        btn.setLayoutX(100);
        btn.setLayoutY(80);
        btn.setText("Hello World");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {
                System.out.println("Hello World");
            }
        });
        root.getChildren().add(btn);        
        primaryStage.setScene(scene);
        primaryStage.setVisible(true);
    }
}

Notre classe Test hérite de la classe Application, c'est la classe principale de notre application (de toute façon c'est la seule :p ), c'est elle qui contient la fonction main() qui est le point d'entrée de notre programme. Pour mieux comprendre ce qu'elle contient, commençons par supprimer le contenu de la fonction start() en laissant juste la dernière ligne. Voici ce que devrait contenir maintenant notre classe Test :

public class Test extends Application {

    public static void main(String[] args) {
        Application.launch(Test.class, args);
    }
    
    @Override
    public void start(Stage primaryStage) {
        
        primaryStage.setVisible(true);
    }
}

La classe Test contient deux fonctions :

  • 1.La fonction main(). Comme je l'ai dit c'est le point d'entrée de notre application. Elle appelle la fonction launch() qui lancera le reste du programme. C'est la seule instruction que doit contenir la fonction main().

  • 2.La fonction start(). Cette fonction est déclenchée par la fonction launch(), elle prend en argument un objet de type Stage. Vous vous souvenez... c'est le théâtre qui contiendra tout ce qui constitue l'application : la scène, les acteurs, etc... Pour l'instant la fonction start() ne fait que rendre visible l'objet Stage, c'est-à-dire la fenêtre de notre application.

Vous pouvez compiler pour voir ce que ça donne :

Image utilisateur

Vous obtenez une fenêtre transparente, il n'y a même pas de fond. C'est à ça que se résume notre objet Stage : une fenêtre absolument vide.
Maintenant qu'on a créé notre théâtre on va pouvoir lui ajouter une scène, pour cela on va effectuer trois actions :

  • 1.On crée le groupe root dont j'ai parlé plus haut, celui qui contiendra tous les objets graphiques

  • 2.On crée l'objet Scene qui contiendra le groupe root.

  • 3.On ajoute l'objet Scene à l'objet Stage

@Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 600, Color.LIGHTBLUE);
        primaryStage.setScene(scene);

        primaryStage.setVisible(true);
    }

Vous pouvez compiler :

Image utilisateur

Notre fenêtre a maintenant un fond grâce à notre objet Scene qui va contenir tous les nœuds graphiques de notre application.

On peut créer et ajouter à notre scène tous les objets que l'on souhaite. Commençons par exemple par créer un cercle. Pour ça on procède en trois temps :

  • 1.On déclare et on construit notre objet de type Circle

  • 2.On règle les paramètres de cet objet comme on le souhaite (sa couleur, sa taille, etc...)

  • 3.On ajoute notre objet au groupe root de notre objet Scene.

@Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 600, Color.LIGHTBLUE);
        primaryStage.setScene(scene);
        
        Circle cercle = new Circle();
        cercle.setCenterX(300);//réglage de la position, de la taille et de la couleur du cercle
        cercle.setCenterY(200);
        cercle.setRadius(100);
        cercle.setFill(Color.YELLOW);
        cercle.setStroke(Color.ORANGE);//réglage de la couleur de la bordure et de son épaisseur
        cercle.setStrokeWidth(5);
        
        root.getChildren().add(cercle);//on ajoute le cercle au groupe root
        primaryStage.setVisible(true);
    }

Si vous faites un copier – coller de ce code, une erreur devrait apparaître. Cette erreur est due au fait que vous n'avez pas importé les bibliothèques nécessaires pour utiliser des objets de type Circle. Pour ça, il existe une formule magique à connaître absolument ;) . C'est le raccourci Ctrl+Maj+I, cela détectera automatiquement les bibliothèques manquantes et les ajoutera en haut de votre feuille de code, vous pouvez vérifier... Quand je code sur Netbeans, j'utilise tout le temps ce raccourci, il est très très pratique ;) .

Voici ce que vous devriez voir si vous compilez :

Image utilisateur

Ajoutons maintenant un rectangle vert à notre scène. Pour cela, créons un objet de type Rectangle et procédons de la même façon que pour le cercle :

@Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 600, Color.LIGHTBLUE);
        primaryStage.setScene(scene);
        
        Circle cercle = new Circle();
        cercle.setCenterX(300);
        cercle.setCenterY(200);
        cercle.setRadius(100);
        cercle.setFill(Color.YELLOW);
        cercle.setStroke(Color.ORANGE);
        cercle.setStrokeWidth(5);
        
        Rectangle rectangle = new Rectangle();
        rectangle.setX(300);
        rectangle.setY(200);
        rectangle.setWidth(300);
        rectangle.setHeight(200);
        rectangle.setFill(Color.GREEN);
        rectangle.setStroke(Color.DARKGREEN);
        rectangle.setStrokeWidth(5);
        rectangle.setArcHeight(30);
        rectangle.setArcWidth(30);
        
        root.getChildren().add(cercle);
        root.getChildren().add(rectangle);//On ajoute le rectangle après le cercle
        primaryStage.setVisible(true);
    }

Une erreur apparaît là encore, mais vous connaissez l'astuce : Ctrl+Maj+I pour importer les bibliothèques manquantes. Mais cette fois-ci on vous donne le choix entre trois bibliothèque pour l'objet Rectangle. Ceci arrivera souvent à l'avenir, dans ce cas choisissez toujours la bibliothèque qui commence par "javafx" : javafx.scene.shape.Rectangle.

Vous pouvez compiler :

Image utilisateur

On voit que notre rectangle apparaît devant notre cercle. C'est parce qu'on a inséré le rectangle au groupe root après avoir inséré le cercle. Si on inverse l'ordre dans lequel on insère ces deux nœuds graphiques :

root.getChildren().add(rectangle);//On ajoute dabord le rectangle
root.getChildren().add(cercle);//puis le cercle

voici le résultat de la compilation :

Image utilisateur

L'ordre d'apparition des nœuds dans notre scène correspond tout simplement à l'ordre dans lequel nous les avons insérés dans notre groupe root.

J'espère que ce chapitre a été clair. La structure du code JavaFX n'a rien de sorcier, elle est assez simple à comprendre et à développer, il suffit de bien organiser ses nœuds et ses groupes de nœuds graphiques. A ce niveau du tutoriel, vous avez déjà compris ce qu'était le principe du langage JavaFX, nous verrons dans la suite comment créer nos propres nœuds graphiques et comment les rendre intéressants.

Pour rendre ce tutoriel un peu amusant, je vous propose d'apprendre à coder en JavaFX à travers la réalisation d'un petit projet. Je décrirais dans le prochain chapitre en quoi consiste ce projet :) .

Exemple de certificat de réussite
Exemple de certificat de réussite