import javax.swing.*; import java.awt.*; import java.util.*; import java.text.*; class Test { static JFrame f; static double minus; static double maxus; public static void main(String[] args) { if(args.length!=2) System.exit(0); minus=Double.parseDouble(args[0]); maxus=Double.parseDouble(args[1]); f=new JFrame("Graphe"); try { //Affichage f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); PanGen pangen=new PanGen(); f.setContentPane(pangen); f.pack(); f.setVisible(true); } catch(Exception e) { e.printStackTrace(); f.dispose(); } } } class PanGen extends JPanel { Grille grille; PanGen() { grille=Grille.faitGrille(this); setPreferredSize(new Dimension(300, 100)); } public void paintComponent(Graphics g) { super.paintComponent(g); //paint background int largact=getWidth(); int hautact=getHeight(); g.clearRect(0, 0, largact, hautact); int y=hautact-50; g.drawLine(40,y,largact-40,y); grille.pregr(g, Test.minus, Test.maxus, largact-80); grille.gengr(g); } } abstract class Grille { //Registre //Valeur stockées par pregr() int absG; int unité; //pointeur de MILLIS double présent; //Temps immédiat double supmin; //Dernier MILLIS avant maxus double minus; double maxus; double facteur; static Grille faitGrille(JComponent jc) { return new GrilleMath(jc); } abstract void pregr(Graphics g, double minus, double maxus, int largeur); abstract void gengr(Graphics g); } //----------------- GrilleMath ------------------ final class GrilleMath extends Grille { //Constantes grille static private double PAS_PIX=5d; double pas; double maxus; double minus; int pasent; int naccent; int compteur; int accetiq; DecimalFormat df; Font normal; Font petit; FontMetrics fmn; FontMetrics fmp; //Largeurs des chiffres, virgule et signe moins int lrgCN, lrgVN, lrgSN; //pour caractères normaux int lrgCP, lrgVP, lrgSP; //pour caractères petits //Constructeur GrilleMath(JComponent jc) { //polices normal=jc.getFont(); petit=normal.deriveFont(normal.getSize2D()*0.8f); fmn=jc.getFontMetrics(normal); fmp=jc.getFontMetrics(petit); //largeurs lrgCN=fmn.charWidth('0'); lrgVN=fmn.charWidth('.'); lrgSN=fmn.charWidth('-'); lrgCP=fmp.charWidth('0'); lrgVP=fmp.charWidth('.'); lrgSP=fmp.charWidth('-'); //formatage nombres DecimalFormatSymbols dfs=new DecimalFormatSymbols(); dfs.setDecimalSeparator(','); df=new DecimalFormat(); df.setGroupingUsed(false); df.setDecimalFormatSymbols(dfs); //Utiliser df.format(double à formater) } void pregr(Graphics g, double minus, double maxus, int largeur) { if(minus>=maxus || largeur<10) return ; int diffm=2; //Importation des variables double espcdbl=maxus-minus; double largdbl=(double)largeur; absG=40; //Détermine l'unité double pixdbl=espcdbl/largdbl; //valeur d'un pixel pas=PAS_PIX*pixdbl; //pas représenté par PAS_PIX pixels maxus+=(pixdbl/2); //correction de maxus pour erreur finale this.minus=minus; this.maxus=maxus; double entlog=Math.floor(Math.log10(pas)); //partie entière du log10 du pas double coefpas=Math.pow(10d, entlog); //coefpas de normalisation du pas pas/=coefpas; //pas normalisé entre 1 et 10 int ndec=0; //nombre de décimales du pas //Sélection du pas entier entre 1 et 10 if(pas>5d) {pas=10d; ndec--;} else if(pas>2d) pas=5d; else if(pas>1d) pas=2d; else if(pas<=1d) pas=1d; pasent=(int)pas; pas*=coefpas; //pas réel //Minimum de l'échelle double nbrpas=Math.ceil(minus/pas); supmin=pas*nbrpas; //en valeur réelle //Détermine la largeur en pixels et en double des étiquettes int pixetiq=largEtiq(g, ndec, entlog); double dbletiq=pixdbl*pixetiq; //Maximum de l'échelle double infmax=pas*Math.floor(maxus/pas); //Initialisation du compteur double minpas, maxpas; //Cherche le nombre de degrés d'accentuation naccent=0; int pasvar=pasent; double pasdbl=pas; accetiq=-1; //remise à zéro de l'accent d'étiquette do { //Pour étiquettes if(accetiq==-1 && pasdbl>=dbletiq) accetiq=naccent; pasvar=chgpas(pasvar); pasdbl=(double)pasvar*coefpas; minpas=pasdbl*Math.ceil(minus/pasdbl); maxpas=pasdbl*Math.floor(maxus/pasdbl); if(minpas>maxus) break; //0 point naccent++; } while(minpas!=maxpas || minpasaccetiq) g.setFont(normal); pasvar=chgpas(pasvar); if(compt%pasvar!=0) break; tiginc+=4; } //Si étiquette activée if(etiq) { tigetiq=10; //Elimination du zéro négatif //Texte indic=df.format(curseur); //Calcule le décalage dectxt=fmn.stringWidth(indic)/2; //Inscrit g.setColor(Color.gray); g.drawString(indic, pix-dectxt, posetiq); g.setColor(Color.black); } else { tigetiq=4; } //Tracer tigette g.drawLine(pix, ordB-tiginc, pix, ordB+tigetiq); //incrémenter le compteur compt+=pasent; } } //Fin de gengr private int largEtiq(Graphics g, int ndec, double entlog) { //Calcul du nombre de décimales ndec+=(entlog<0)?(int)Math.abs(entlog):0; if(ndec<0) ndec=0; //Formate la sortie avec les décimales // df.setMaximumFractionDigits(ndec); // df.setMinimumFractionDigits(ndec); //Fabrique l'étiquette modèle de largeur //Trouve la valeur numérique double nbrmod; //valeur numérique if(minus>=0d && maxus>0d) { //minus positif ou nul et maxus positif nbrmod=Math.floor(maxus); } else if(maxus<=0) { //minus négatif et maxus négatif ou nul nbrmod=Math.ceil(minus); } else { //minus négatif et maxus positif //Signe moins non pris en compte si maxus>-minus avec même nombre de chiffres if(maxus>-minus) nbrmod=Math.floor(maxus); else nbrmod=Math.ceil(minus); } //Forme une chaîne modèle String smod=df.format(nbrmod); //Calcule le nombre de pixels de la chaîne modèle int pixmod=fmn.stringWidth(smod); if(ndec!=0) pixmod+=lrgVN+(ndec*lrgCN); //Ménage un espacement arbitraire entre étiquettes pixmod+=10; return pixmod; } private int chgpas(int pasent) { int temp=pasent; while(temp>=10) temp/=10; if(temp==5) pasent*=2; else pasent*=5; return pasent; } } //Fin GrilleMath