Graphismes avec Java FX

Ajout d'une animation tenant compte du temps écoulé

Afin de pouvoir "animer" l'aiguille, le programme doit maintenant redessiner périodiquement la fenêtre en positionnant l'aiguille en fonction du temps écoulé.
Nous allons utiliser pour cela la classe AnimationTimer. Ajouter dans la classe EchantillonController les lignes suivantes (le commentaire est facultatif!) :

AnimationTimer mouvement=new AnimationTimer(){
  @Override 
  public void handle(long now){
   // le code à exécuter périodiquement est à écrire ici 
  }
}; 
et ajouter l'importation de AnimationTimer.

Une fois l'AnimationTimer démarré, le code écrit à l'emplacement indiqué sera exécuté régulièrement, environ 60 fois par secondes, et la variable now indique le temps du système en nanosecondes. Le comportement du programme est donc analogue à celui d'une boucle.

Pour réaliser le chronomètre, on va déclarer deux nouvelles variables dans la classe EchantillonController :

double tempsDeDepart;
double tempsCourant; 
et compléter le code de l'AnimationTimer ainsi :
AnimationTimer mouvement=new AnimationTimer(){
  @Override 
  public void handle(long now){
    if (tempsDeDepart==0){ 
      tempsDeDepart=now;
	  tempsCourant=now;
    } //Lors du premier passage, tempsDeDepart et tempsCourant sont initialisés à la valeur actuelle du temps système
    if (now-tempsCourant>1e9){  // vérifie si le temps actuel est supérieur d'au moins 1s au dernier temps enregistré dans tempsCourant 
      double secondes=Math.floor((now-tempsDeDepart)/1e9);  //Calcule la valeur en secondes de la durée écoulée depuis le dernier temps enregistré 
      traceCadran(secondes*Math.PI/30); //Appelle la méthode traceCadran en indiquant une position d'aiguille calculée d'après cette durée en secondes.
      tempsCourant=now; // Enregistre la valeur du temps système dans la variable tempsCourant 
    }
  }
};
 

Il ne reste plus qu'à déclencher le timer en ajoutant à la fin de la méthode initialize la ligne

 mouvement.start(); 

juste après la ligne
traceCadran(0); 

Le code complet contenu dans EchantillonController est alors :
 
package application;

import javafx.animation.AnimationTimer;
import javafx.fxml.FXML;
import javafx.geometry.VPos;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.ImagePattern;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;

public class SampleController {
	
  @FXML Canvas fond; 
  GraphicsContext gc;
  double largeur;
  double hauteur;
  double rayon;
  double lAiguille;
  double tempsDeDepart=0;
  double tempsCourant=0;
  Image decor=new Image("images/Desert.jpg");
       
  AnimationTimer mouvement=new AnimationTimer(){
    @Override 
    public void handle(long now){
      if (tempsDeDepart==0){
        tempsDeDepart=now;
		tempsCourant=now;
      }
      if (now-tempsCourant>1e9){
        double secondes=Math.floor((now-tempsDeDepart)/1e9);
        traceCadran(secondes*Math.PI/30);
        tempsCourant=now;
      }
    }
  };
       
  private void traceCadran(double inclinaison){
    gc.drawImage(decor,-largeur/2,-hauteur/2,largeur,hauteur);
    ImagePattern motif=new ImagePattern(decor);
    gc.setFill(motif);
    for (int i=0;i<12;i=i+1){
      gc.fillOval(rayon*Math.cos(i*Math.PI/6)-8,rayon*Math.sin(i*Math.PI/6)-8, 16, 16);
    }
		
    gc.setFont(new Font(20));
    gc.setTextAlign(TextAlignment.CENTER);
    gc.setTextBaseline(VPos.CENTER);
    gc.setFill(Color.BEIGE);
    gc.fillText("0",0,-rayon-20);
    gc.fillText("15", rayon+20, 0);
    gc.fillText("30",0, rayon+20);
    gc.fillText("45", -rayon-20, 0);
		
    gc.setStroke(Color.color(0.8,0.9,1));
    gc.setLineWidth(4);
    inclinaison=inclinaison-Math.PI/2;
    gc.strokeLine(0,0,lAiguille*Math.cos(inclinaison),lAiguille*Math.sin(inclinaison));	
  }
	
  @FXML void initialize(){	
    gc=fond.getGraphicsContext2D();
    largeur=fond.getWidth();
    hauteur=fond.getHeight();
    rayon=largeur/2.5;
    lAiguille=rayon*4/5;
    gc.translate(largeur/2,hauteur/2);		
	traceCadran(0);
    mouvement.start();
  }
}
Si tout va bien, l'aiguille tourne de 1/60ème de tour à chaque seconde.
 
Licence Creative Commons
licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé
Auteur : Nathalie Bonnin
Professeur de Physique, Chimie, Informatique au lycée La Martinière Monplaisir (Lyon 8ème)
Contact :
nathalie.bonnin (chez) scientillula.net
Licence Creative Commons
La totalité du contenu du site Scientillula.net appartient à Nathalie Bonnin et est mise à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé