tete du loic

 Loïc YON [KIUX]

  • Enseignant-chercheur
  • Référent Formation Continue
  • Responsable des contrats pros ingénieur
  • Référent entrepreneuriat
  • Responsable de la filière F2 ingénieur
  • Secouriste Sauveteur du Travail
mail
loic.yon@isima.fr
phone
(+33 / 0) 4 73 40 50 42
location_on
ISIMA
  • twitter
  • linkedin
  • viadeo

[JavaFX] Pustules

Date de première publication : 2018/02/07

Voici "quelques" éléments de réponse sur l'exercice Pustules. La première partie explore les solutions avec uniquement des composants standards. La deuxième modélise un nouveau composant.

Sauce aux composants standards

La première solution consiste à utiliser un composant standard de type Button. L'idée est d'analyser le texte du bouton que l'on sait être un entier pour le changer quand il faut :


Button b = new Button("0");

Un gestionnaire par bouton (1)

Le gestionnaire de l'événement est une implémentation d'EventHandler

class Gestionnaire implements EventHandler<ActionEvent> {
}

Si le gestionnaire connait le bouton, le code pour réagir est simple (à placer dans la méthode handle()) :


int v = Integer.parseInt(bouton.getText());
bouton.setText(String.valueOf(v+1));

Bien entendu, il faut ajouter bouton comme attribut de la classe Gestionnaire et fixer cet attribut avec une méthode set() ou à la création de l'objet Gestionnaire :

Button b = new Button("0");
b.setOnAction(new Gestionnaire(b));

Un gestionnaire par bouton (2)

On peut se contenter d'utiliser une classe anonyme comme gestionnaire comme l'a montré le HelloWorldJavaFX

b.setOnAction(new EventHandler<ActionEvent>() {});

Il faut juste trouver le bouton concerné par l'astuce suivante :


Button b = (Button)e.getSource();
int    v = Integer.parseInt(b.getText());
b.setText(String.valueOf(v+1));

e est un objet événement. Le code doit être placé dans la méthode handle()

Un gestionnaire pour tous les boutons

Au point précédent, j'ai proposé autant de gestionnaires de l'action que de boutons mais le code est indépendant du bouton, on peut donc naturellement en proposer une version unique :


class GestionnaireUnique implements EventHandler<ActionEvent> {
}

et reprendre la méthode handle(). On peut même ne pas utiliser de classe du tout en employant une lambda :


b.setOnAction((ActionEvent e)->{});

Le code de la lambda est directement celui de handle()

Un bouton spécialisé

La base

Le bouton de l'application Pustules est un bouton particulier, il semble donc légitime (au niveau modélisation objet) de créer une nouvelle classe.


class MonBouton extends Button {
  
} 

Cette classe sera dotée d'un attribut compteur initialisé dans le constructeur :


public MonBouton() {
   super("0");    // initialiser le premier texte
   compteur = 0;  
} 

(Pour rappel, les constructeurs ne sont jamais hérités et les attributs ont des valeurs par défaut si celles-ci ne sont pas fixées à la construction) et l'attribut sera incrémenté par la méthode idoine :


public void incrementer() {
   ++compteur;
   setText(String.valueOf(compteur));
} 

Ce bouton ne réagit pas aux événements de type ActionEvent

Son propre gestionnaire

Là encore, la situation la plus logique est que la classe implémente elle-même l'interface EventHandler, c'est-à-dire que l'on estime que le bouton est lui-même le plus apte à réagir à cet événement.


class MonBouton extends Button implements EventHandler<ActionEvent> {
  
} 

Cela nous invite naturellement à implémenter la méthode handle() :


public void handle(ActionEvent e) {
   incrementer();  
} 

Pourtant, le bouton ne réagit pas encore à l'action, il faut le spécifier à la construction :


public MonBouton() {
   super("0");    // initialiser le premier texte
   compteur = 0;  
   setOnAction(this);
} 

Sans gestionnaire

En fait, il n'était pas nécessaire d'implémenter l'interface EventHandler si l'on utilise une référence de méthode. Il suffit que la méthode ait un ActionEvent en paramètre :


public MonBouton() {
   super("0");    // initialiser le premier texte
   compteur = 0;  
   setOnAction(this::incrementer);
} 

Vous devez modifier incrementer() en conséquence.


public void incrementer(ActionEvent e)