package fr.univParisDiderot.phys; import javax.swing.*; import java.awt.*; import java.awt.image.BufferStrategy; /** * La classe <code>FramedCanvas</code> permet de créer une fenêtre * simple et de dessiner dedans. * * <P>Voici un exemple d'utilisation de FramedCanvas: * <PRE> * FramedCanvas dessin = new FramedCanvas(200,200); * for (i=0; i<200; i+=4) { * dessin.drawLine(0,i,199,199-i); * dessin.drawLine(i,0,199-i,199); * dessin.repaint(); * } * dessin.discard(); * </PRE> * * Noter que les commandes pour dessiner (drawLine, ...) dessinent sur * une feuille qui n'est <em>pas</em> visible. Pour l'afficher dans la * fenêtre, il faut invoquer la méthode repaint(). De même, * clearArea() efface le contenu de la feuille de dessin, mais pas de * la fenêtre, ce qui permet de préparer le dessin suivant tout en * ayant le dessin précédent à l'écran. * * @author Adrian Daerr (adrian.daerr'at'univ-paris-diderot.fr), * inspiré par du code de Jean-Baptiste Yunes * (Jean-Baptiste.Yunes'at'liafa.jussieu.fr) * @version 0.1 */ public class FramedCanvas extends Canvas { private JFrame theFrame = null; private int width, height; private BufferStrategy backing; private Graphics backingGraphics; private Color fgColor=Color.BLACK, bgColor; /** Crée une fenêtre et l'affiche à l'écran. * * @param width largeur du dessin * @param height hauteur du dessin */ public FramedCanvas(int width, int height) { setSize(width,height); if (theFrame != null) return; theFrame = new JFrame("Dessin"); theFrame.setResizable(false); theFrame.getContentPane().add((Canvas)this); theFrame.pack(); theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); theFrame.setVisible(true); createBackingStore(); bgColor = UIManager.getColor("Panel.background"); if (bgColor == null) bgColor = Color.WHITE; } /** Crée une fenêtre et l'affiche à l'écran. * * @param width largeur du dessin * @param height hauteur du dessin * @param bgColor couleur de fond (utilisée par clearArea()) */ public FramedCanvas(int width, int height, Color bgColor) { this(width,height); this.bgColor = bgColor; } /** Change la taille de la fenêtre. Change aussi la feuille de dessin. * * @param width largeur du dessin * @param height hauteur du dessin */ public void setSize(int width,int height) { super.setSize(width,height); this.width = width; this.height = height; if (isDisplayable()) createBackingStore(); } private void createBackingStore() { createBufferStrategy(2); backing = getBufferStrategy(); backingGraphics = backing.getDrawGraphics(); } /** Donne les dimensions actuelles de la feuille de dessin. */ public Dimension getPreferredSize() { return new Dimension(width,height); } /** Paint la feuille de dession à l'écran; ne pas invoquer * directement, utiliser repaint() qui invoquera cette méthode * avec le bon paramètre <code>g</code>. */ public void paint(Graphics g) { update(g); } /** Paint la feuille de dession à l'écran; ne pas invoquer * directement, utiliser repaint() qui invoquera cette méthode * avec le bon paramètre <code>g</code>. */ public void update(Graphics g) { if (backing == null) createBackingStore(); // ligne suivante pose pb si backingGraphics est utilisé entre // ici et la dernière ligne de la méthode; synchroniser? //if (backingGraphics != null) backingGraphics.dispose(); if (backing.contentsRestored()) System.err.println("backing buffer contents restored"); backing.show(); if (backing.contentsLost()) System.err.println("backing buffer contents lost"); backingGraphics = backing.getDrawGraphics(); } /** Dessine une ligne de (x0,y0) à (x1,y1) dans la couleur * actuelle. L'origine se situe dans le coin supérieur gauche. * * @see #setColor */ public void drawLine(int x0,int y0,int x1, int y1) { if (backingGraphics==null) return; backingGraphics.drawLine(x0,y0,x1,y1); } /** Donne au point (x,y) la couleur actuelle. * * @see #setColor */ public void drawPoint(int x,int y) { drawLine(x,y,x,y); } /** Ajuste la couleur actuelle. */ public void setColor(Color c) { fgColor = c; if (backingGraphics==null) return; backingGraphics.setColor(c); } /** Ajuste la couleur actuelle au mélange RVB donné. * * @param c1 intensité du rouge entre 0 (absent) et 255 (saturé) * @param c2 intensité du vert * @param c3 intensité du bleu */ public void setColor(int c1,int c2,int c3) { fgColor = new Color(c1,c2,c3); if (backingGraphics==null) return; backingGraphics.setColor(fgColor); } /** Équivaut à un appel de setColor(level, level, level). * * @see #setColor */ public void setGray(int level) { setColor(level, level, level); } /* Retourne la couleur actuelle. */ public Color getColor() { return fgColor; } /** Efface la feuille de dessin. */ public void clearArea() { if (backingGraphics==null) return; //backingGraphics.clearRect(0,0,width,height); backingGraphics.setColor(bgColor); backingGraphics.fillRect(0,0,width,height); backingGraphics.setColor(fgColor); } /** Renvoie une référence à la feuille de dessin. Permet de faire * des manipulations directes au-delà de ce qui est possible à * travers les méthodes de FramedCanvas (drawLine etc.). */ public Graphics getBackingGraphics() { return backingGraphics; }; /** Détruit la fenêtre et le dessin qu'elle contient. */ public void discard() { if (theFrame==null) return; theFrame.setVisible(false); theFrame.dispose(); theFrame=null; } /** Ne fait rien pendant une durée déterminée. */ public static void sleep(int millisecondes) { try { Thread.sleep(millisecondes); } catch(InterruptedException ie) {} } }