You are on page 1of 6

Exercice comment

Graphique en camembert
1. Enonc

Auteur : cj-tronquet@ifrance.com

Ecrire une applet permettant, grce des paramtres dans le fichier html, de dessiner un graphique en camembert. Dans le fichier html, on pourra choisir le nombre de catgories, leur nom, leur valeur et leur couleur, ainsi que le titre du graphique et sa couleur de fond. Voici un exemple de ralisation :

2. Solution commente
2.1. Passage de paramtres
Une applet peut rcuprer des paramtres qui sont crits dans la page html contenant lapplet. Les balises ncessaires sont <PARAM NAME=nom_param VALUE="valeur_param_texte"> ou <PARAM NAME=nom_param VALUE=valeur_param_nb> Lapplet va ainsi pouvoir lire la valeur de ces paramtres grce la fonction : getParameter("nom_param") On pourra ainsi passer notre applet toutes les donnes utiles la gnration dun graphique. Cest dans la mthode init que lon va rcuprer ainsi ces paramtres.

2.2. Calcul des positions


On utilise un tableau dangles qui contient la valeur de langle de chaque secteur du graphique. A partir de cet angle, on va pouvoir, grce au thorme de Pythagore, calculer toutes les coordonnes dont nous avons besoin.

Ainsi, dans la figure ci dessous, connaissant langle r (en radian), on peut connatre les coordonnes du point A sur le cercle :

ax = rayon cos(r ) ay = rayon sin( r )

A ay r 0 ax

3. Code Source
import java.awt.*; import java.io.*; import java.lang.*;

public class Graphique extends java.applet.Applet { String titre; // titre du graphique Font font; FontMetrics fontMetrics; int hauteurTitre = 15; int nbCateg; int tabValeurs[]; Color tabCouleurs[]; String tabLabels[]; float tabPourcents[]; float tabAngles[]; int largeurLabelMax = 0; int largeurValeurMax = 0; int max = 0; int largeurStr=0; boolean showLabel=true; // true si on veut afficher les labels boolean showPourcent=true; // true si on veut afficher les pourcentages int lx=0,ly=0; //position du label int cx=0,cy=0; //position du centre du cercle

public synchronized void init() { String temp; font = new java.awt.Font("Arial", Font.BOLD, 12); fontMetrics = getFontMetrics(font); String couleurFond=getParameter("couleurFond"); // couleur de fond du graphique if (couleurFond==null) setBackground(Color.white); else{ if (couleurFond.equals("rouge")) { setBackground(Color.red); } else if (couleurFond.equals("vert")) {

setBackground(Color.green); } else if (couleurFond.equals("bleu")) { setBackground(Color.blue); } else if (couleurFond.equals("rose")) { setBackground(Color.pink); } else if (couleurFond.equals("orange")) { setBackground(Color.orange); } else if (couleurFond.equals("magenta")) { setBackground(Color.magenta); } else if (couleurFond.equals("cyan")) { setBackground(Color.cyan); } else if (couleurFond.equals("blanc")) { setBackground(Color.white); } else if (couleurFond.equals("jaune")) { setBackground(Color.yellow); } else if (couleurFond.equals("gris")) { setBackground(Color.gray); } else if (couleurFond.equals("grisFonc")) { setBackground(Color.darkGray); } else { setBackground(Color.white); } } titre = getParameter("titre"); // titre du graphique if (titre == null) { titre = "Graphique"; } temp = getParameter("nbCateg"); // nombre de catgories if (temp == null) { nbCateg = 5; } else { nbCateg = Integer.parseInt(temp); } temp = getParameter("labels"); // veut-on voir les labels ? if (temp == null) { showLabel = true; } else { if (temp.equalsIgnoreCase("OUI")) showLabel = true; if (temp.equalsIgnoreCase("NON")) showLabel = false; else showLabel = true; } temp = getParameter("pourcentages"); // veut-on voir les pourcentages ? if (temp == null) { showPourcent = true; } else { if (temp.equalsIgnoreCase("OUI")) showPourcent = true; if (temp.equalsIgnoreCase("NON")) showPourcent = false; else showPourcent = true; } tabValeurs = new int[nbCateg]; tabCouleurs = new Color[nbCateg]; tabLabels = new String[nbCateg]; tabPourcents= new float[nbCateg]; tabAngles = new float[nbCateg]; float somme=0;

for (int i=0; i < nbCateg; i++) { temp = getParameter("valeur" + (i+1)); // valeur de la ime catgorie if (temp != null) { try { tabValeurs[i] = Integer.parseInt(temp);

} catch (NumberFormatException e) { tabValeurs[i] = 0; } } somme += tabValeurs[i]; if (tabValeurs[i] > max) { max = tabValeurs[i]; } temp = getParameter("label"+ (i+1) ); // label de la ime catgorie tabLabels[i] = (temp == null) ? "" : temp; largeurLabelMax = Math.max(fontMetrics.stringWidth((String)(tabLabels[i])), largeurLabelMax);

temp = getParameter("couleur"+ (i+1) ); // couleur de la ime catgorie if (temp != null) { if (temp.equals("rouge")) { tabCouleurs[i] = Color.red; } else if (temp.equals("vert")) { tabCouleurs[i] = Color.green; } else if (temp.equals("bleu")) { tabCouleurs[i] = Color.blue; } else if (temp.equals("rose")) { tabCouleurs[i] = Color.pink; } else if (temp.equals("orange")) { tabCouleurs[i] = Color.orange; } else if (temp.equals("magenta")) { tabCouleurs[i] = Color.magenta; } else if (temp.equals("cyan")) { tabCouleurs[i] = Color.cyan; } else if (temp.equals("blanc")) { tabCouleurs[i] = Color.white; } else if (temp.equals("jaune")) { tabCouleurs[i] = Color.yellow; } else if (temp.equals("gris")) { tabCouleurs[i] = Color.gray; } else if (temp.equals("grisClair")) { tabCouleurs[i] = Color.darkGray; } else { tabCouleurs[i] = Color.gray; } } else { tabCouleurs[i] = Color.gray; } } float facteur = 100 / somme; for (int i=0; i < nbCateg; i++) { tabPourcents[i]= tabValeurs[i] * facteur; // calcul des pourcentages tabAngles[i] = (float) (tabPourcents[i] * 3.6) ; // calcul de l'angle (360/100) } }

// dessin du graphique public synchronized void paint(Graphics g) { int x=0; int y=0; int largeur=0,hauteur=0; //coordonnes des points de liaison des portions sur la circonfrence du cercle int ax=0,ay=0; int px=0,py=0; //coordonnes des pourcentages int angleRad=0; largeur=hauteur=Math.min((getSize().largeur - 100),(getSize().hauteur - 100)); x=y=50; if ( getSize().largeur > largeur ){ x = (getSize().largeur - largeur ) /2 ; }

cx = x + largeur/2; cy = y + hauteur/2; angleRad = largeur/2; // dessiner le titre du graphique largeurStr=fontMetrics.stringWidth(titre); Font fnt = new java.awt.Font("Arial", Font.BOLD, 16); g.setFont(fnt); g.setColor(Color.white); g.drawString(titre,((getSize().largeur - largeurStr )/2),15); g.setFont(font); int angleDepart=90; int angleCourant=0; int angleCourantCumul=0; int angleLabelCumul= (int) (tabAngles[0]/2); for (int i=0; i < nbCateg; i++) { angleCourant = (int) Math.round(tabAngles[i]); g.setColor((Color)tabCouleurs[i]); if (i==(nbCateg-1)){ //dernire portion angleCourant = 360 - angleCourantCumul; // replissage de la portion g.fillArc(x,y,largeur,hauteur,angleDepart,(-angleCourant)); // contour de la portion g.setColor(Color.black); g.drawArc(x,y,largeur,hauteur,angleDepart,(-angleCourant)); if (showLabel){ // position du label lx= (int)(cx+(angleRad*Math.cos((angleLabelCumul*3.14f/180)-3.14f/2))); ly = (int)(cy+(angleRad*Math.sin((angleLabelCumul*3.14f/180)-3.14f/2))); ajustementLabel(i); //affichage du label g.drawString((String)tabLabels[i],lx,ly); } if (showPourcent){ //position du pourcentage px = (int)(cx+((angleRad*2/3)*Math.cos((angleLabelCumul*3.14f/180) - 3.14f/2))); py = (int)(cy+((angleRad*2/3)*Math.sin((angleLabelCumul*3.14f/180) - 3.14f/2))); g.drawString(String.valueOf(Math.round(tabPourcents[i]))+"%",px,py); } break; // quitter la boucle for } // remplissage de la portion g.fillArc(x,y,largeur,hauteur,angleDepart,(-angleCourant)); // dessin du contour g.setColor(Color.black); g.drawArc(x,y,largeur,hauteur,angleDepart,(-angleCourant)); angleCourantCumul +=angleCourant; //calcul du point extremit de la portion sur le cercle ax = (int) (cx + ( angleRad * Math.cos((angleCourantCumul * 3.14f/180) - 3.14f/2))); ay = (int) (cy + ( angleRad * Math.sin((angleCourantCumul * 3.14f/180) - 3.14f/2))); //dessin du rayon g.drawLine(cx,cy,ax,ay); if (showLabel){ // calcul de la position et affichage du label lx = (int) (cx + ( angleRad * Math.cos((angleLabelCumul * 3.14f/180) - 3.14f/2))); ly = (int) (cy + ( angleRad * Math.sin((angleLabelCumul * 3.14f/180) - 3.14f/2))); ajustementLabel(i); g.drawString((String)tabLabels[i],lx,ly);

} if (showPourcent){ // calcul de la position et affichage du pourcentage px = (int) (cx + ((angleRad*2/3) * Math.cos((angleLabelCumul * 3.14f/180) - 3.14f/2))); py = (int) (cy + ((angleRad*2/3) * Math.sin((angleLabelCumul * 3.14f/180) - 3.14f/2))); largeurStr = fontMetrics.stringWidth(Math.round(tabPourcents[i])+"%"); g.drawString( String.valueOf(Math.round(tabPourcents[i]))+"%", (px - largeurStr/2), py); } angleLabelCumul = angleLabelCumul + (int) (tabAngles[i]/2 + tabAngles[i+1]/2); angleDepart += (-angleCourant); } // dessin du dernier rayon g.setColor(Color.black); g.drawLine(cx,cy,cx,cy-angleRad); } // ajustement de la position du label private void ajustementLabel(int i){ if ( (lx > cx) && (ly < cy) ){ lx +=5; ly -=5; } if ( (lx > cx) && (ly > cy) ){ lx +=5; ly +=10; } if ( (lx < cx) && (ly > cy) ){ largeurStr=fontMetrics.stringWidth(tabLabels[i]); lx -= largeurStr+5; if (lx < 0) lx=0; } if ( (lx < cx) && (ly < cy) ){ largeurStr=fontMetrics.stringWidth(tabLabels[i]); lx -= largeurStr+5; if (lx < 0) lx=0; } } }