FAQ JavaFXConsultez toutes les FAQ

Nombre d'auteurs : 4, nombre de questions : 507, dernière mise à jour : 2 novembre 2016  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum JavaFX de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.


SommaireSceneGraphFXML et SceneBuilderContrôleur (8)
précédent sommaire suivant
 

Un contrôleur est une classe externe au fichier FXML, généralement écrite en Java, qui est chargée par le chargeur FXML en même temps que le fichier FXML. Cette classe permet de manipuler les entités nommées décrites dans le fichier FXML, d'y accéder depuis le reste de votre application ou même de modifier le contenu de l'arborescence décrite dans le FXML.

Un contrôleur doit être déclaré dans une classe publique disposant du constructeur par défaut ou d'un constructeur public sans paramètre.

Par exemple :

Code Java : Sélectionner tout
1
2
public class MyController { 
}

Ce code définit un contrôleur vide.

Mis à jour le 3 septembre 2014 bouye

Pour déclarer un contrôleur dans un fichier FXML, il faut ajouter l'attribut fx:controller sur l’élément racine du document FXML. Cet attribut doit contenir le chemin complet vers la classe servant de contrôleur pour ce FXML.

Par exemple :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>  
  
<?import java.lang.*?>  
<?import java.util.*?>  
<?import javafx.scene.*?>  
<?import javafx.scene.layout.*?>  
  
<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/>

Une exception sera levée lors du chargement du FXML si la classe n'est pas présente sur le CLASSPATH ou n'est pas accessible.

Mis à jour le 30 septembre 2014 bouye

Pour accéder au contrôleur d'un fichier FXML, après chargement de ce fichier, il faut invoquer la méthode getController() du chargeur.

Par exemple, soit le fichier FXML suivant :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>  
  
<?import java.lang.*?>  
<?import java.util.*?>  
<?import javafx.scene.*?>  
<?import javafx.scene.layout.*?>  
  
<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/>

Pour accéder à son contrôleur, il suffit de faire :

Code Java : Sélectionner tout
1
2
3
4
final URL fxmlURL = getClass().getResource("monFXML.fxml");  
final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL);  
final Node node = fxmlLoader.load(); 
final TestController controler = fxmlLoader.getController();

Mis à jour le 30 septembre 2014 bouye

L'interface javafx.fxml.Initializable est une interface optionnelle que votre contrôleur peut implémenter si besoin. Cette interface définit la méthode initialize() qui sera invoquée au chargement du FXML après l'injection des ressources du FXML dans le contrôleur.

Par exemple :

Code Java : Sélectionner tout
1
2
3
4
5
6
public class MyController implements Initializable { 
    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
        // Faire les initialisations avant affichage ici. 
    } 
}

Mis à jour le 30 septembre 2014 bouye

Pour injecter des ressources dans un contrôleur, chaque ressource doit avoir, dans sa définition dans le fichier FXML, un nom unique déclaré avec l'attribut fx:id. Il vous faut ensuite déclarer des variables équivalentes, avec les types appropriés, dans le contrôleur en les annotant javafx.fxml.FXML (@FXML). Au chargement du FXML, les références des objets créés seront injectées dans le contrôleur.

Par exemple :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?> 
  
<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 
  
<AnchorPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MyController">  
    <children> 
        <Label fx:id="label"/> 
    </children> 
</AnchorPane>

Il est alors possible d'utiliser un contrôleur similaire au code suivant :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
public class MyController implements Initializable {  
    @FXML 
    private AnchorPane root; 
    @FXML 
    private Label label; 
  
    @Override  
    public void initialize(URL location, ResourceBundle resources) {  
        // Faire les initialisations avant affichage ici.  
    }  
}

La méthode initialize() sera invoquée après l'injection des valeurs dans le contrôleur.

Si un élément dans le fichier FXML est déclaré avec un attribut fx:id qui n'a pas d’équivalent dans les variables annotées par @FXML dans le contrôleur, alors le nœud graphique ne sera pas directement accessible depuis le code du contrôleur.

Si le contrôleur dispose d'une variable annotée par @FXML qui n'a pas d’équivalent dans les éléments disposant d'attributs fx:id dans le fichier FXML, alors cette variable restera à la valeur null après injection.

Mis à jour le 30 septembre 2014 bouye

Lorsqu'on inclut un fichier FXML (le fichier secondaire) dans un autre fichier FXML (le fichier principal), il est possible de lui donner également un attribut fx:id. Cette valeur permet de déclarer implicitement une référence vers le contrôleur du FXML inclus (le contrôleur secondaire) depuis le contrôleur du FXML maitre (le contrôleur principal).

Prenons ce simple fichier FXML qui sera le fichier secondaire, test.fxml :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?> 
  
<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.layout.*?> 
  
<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.TestController"/>

Et disposant du contrôleur secondaire suivant :

Code Java : Sélectionner tout
1
2
public class TestController {  
}

Et incluons-le dans un autre FXML, le fichier principal, master.fxml :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?> 
  
<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.layout.*?> 
  
<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MasterController"> 
    <children> 
        <fx:include fx:id="test" source="test.fxml"/> 
    </children> 
</AnchorPane>

Alors il est possible d'injecter implicitement une référence vers le contrôleur secondaire dans notre contrôleur principal en utilisant l'identifiant <identifiant du FXML secondaire>Controller. Par exemple :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
public class MasterController{  
    // Le nœud racine de notre FXML secondaire sera injecté dans cette variable. 
    @FXML 
    private AnchorPane test; 
    // Le contrôleur de notre FXML secondaire sera injecté dans cette variable. 
    @FXML 
    private TestController testController; 
}

Mis à jour le 30 septembre 2014 bouye

Il est possible d'invoquer une méthode du contrôleur depuis le document FXML, par exemple en réaction au clic d'un bouton, en spécifiant le nom de la méthode préfixé du caractère #.

Par exemple :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>  
  
<?import java.lang.*?>  
<?import java.util.*?>  
<?import javafx.scene.*?>  
<?import javafx.scene.control.*?>  
<?import javafx.scene.layout.*?>  
  
<StackPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="test.MyController">   
    <children>  
        <Button fx:id="button" onAction="#onButtonActivated"/>  
    </children>  
</StackPane >

Il faut ensuite déclarer la méthode dans le corps du contrôleur. On prendra soin d’annoter la méthode par @FXML.

Par exemple :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
public class MyController { 
  
    @FXML 
    private void onButtonActivated() { 
        System.out.println("Salut le monde !"); 
    } 
}

Il est également possible de définir une méthode recevant un paramètre de type ActionEvent :

Code Java : Sélectionner tout
1
2
3
4
@FXML 
private void onButtonActivated(final ActionEvent actionEvent) { 
    System.out.println("Salut le monde !"); 
}

Dans le cas où deux méthodes seraient déclarées dans le contrôleur avec des noms identiques, c'est la méthode acceptant un paramètre de type ActionEvent qui sera invoquée en priorité.

Une exception sera levée au chargement du fichier FXML si aucune méthode portant ce nom n'est définie ou si elle n'est pas annotée par l'annotation @FXML.

Mis à jour le 3 octobre 2014 bouye

Il est possible d'injecter un contrôleur dans un FXML qui n'en a pas de défini. Pour cela, il suffit d'invoquer la méthode setController() du chargeur FXMLLoader avant l'appel à sa méthode load().

Prenons le fichier FXML suivant :

Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?> 
  
<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 
  
<VBox id="VBox" spacing="10" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> 
    <Button fx:id="button1" text="Button1" onAction="#handleButton1"/> 
    <Button fx:id="button2" text="Button2" onAction="#handleButton2"/> 
    <Button fx:id="button3" text="Button3" onAction="#handleButton3"/> 
    <Button fx:id="button4" text="Button4" onAction="#handleButton4"/> 
    <Button fx:id="button5" text="Button5" onAction="#handleButton5"/> 
</VBox>

En temps normal, il n'est pas possible de charger ce fichier FXML. En effet, nous référençons des méthodes sur les propriétés onAction des boutons, mais n'avons nulle part de contrôleur dans lequel ces méthodes sont définies : une exception sera donc levée si nous essayons de le charger.

Prenons la classe suivante qui va nous servir de contrôleur :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public final class TestInjectionController implements Initializable { 
  
    @FXML 
    private Button button1; 
    @FXML 
    private Button button2; 
    @FXML 
    private Button button3; 
    @FXML 
    private Button button4; 
    @FXML 
    private Button button5; 
  
    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
        System.out.println("Initialize !"); 
    } 
  
    @FXML 
    private void handleButton1() { 
        System.out.println("Bouton 1"); 
    } 
  
    @FXML 
    private void handleButton2() { 
        System.out.println("Bouton 2"); 
    } 
  
    @FXML 
    private void handleButton3() { 
        System.out.println("Bouton 3"); 
    } 
  
    @FXML 
    private void handleButton4() { 
        System.out.println("Bouton 4"); 
    } 
  
    @FXML 
    private void handleButton5() { 
        System.out.println("Bouton 5"); 
    } 
}

Nous pouvons injecter cette classe en tant que contrôleur de notre fichier FXML en faisant :

Code Java : Sélectionner tout
1
2
3
4
final URL fxmlURL = getClass().getResource("testinjection.fxml"); 
final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL); 
fxmlLoader.setController(new TestInjectionController()); 
final Node node = fxmlLoader.load();

Désormais, nous pouvons charger le FXML sans lever d'exception et notre contrôleur prend en charge les actions des boutons. Nous pouvons voir également que la méthode initialize() du contrôleur est correctement invoquée.

Mis à jour le 16 octobre 2014 bouye

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -