package pg.coursjava.logo; import java.awt.* ; import java.awt.event.* ; /** * * Un objet de cette classe définit une fenêtre munie d'un repère dont :
* - l'origine est au centre de la fenêtre,
* - l'axe des X est horizontal et orienté de gauche à droite,
* - l'axe des Y vertical et orienté de bas en haut.
*
* De plus cette fenêtre définit un objet Plume qui permet de dessiner "à la logo".
* (la plume possède des méthodes "à la Logo" pour écrire dans la fenêtre : avancer, tourner, * lever, baisser, ...).
* * @author Philippe Genoud d'après Laurent Mounier * @version 15 février 1999 */ public class Fenetre extends Frame implements ActionListener, MouseListener { private Plume laPlume; // gestion de la fenetre d'affichage int offsetX; int offsetY ; // decalage de l'origine du repere private Image offImage; // image associe a l'offscreen private Graphics offGraphics; // contexte graphique de l'offscreen private Button boutonQuitter = new Button ("Quitter ...") ; // gestion des clics souris private boolean clic=false; private boolean attendsClic=false ; private int clicX = 0; private int clicY = 0; // position du dernier clic souris private Color couleurPlume ; // couleur courante /** * * crée et affiche une fenêtre de dessin "à la logo".
* Une plume de classe Plume est automatiquement créee et est associée à la fenêtre.
* La plume est placée au centre de la fenêtre, en position basse avec un cap de 0 * (sur axe des x positifs). * * @param titre le titre de la fenêtre. * @param largeur largeur de la fenêtre en pixels. * @param hauteur hauteur de la fenetre en pixels. */ public Fenetre (String titre, int largeur, int hauteur) { /* on cree la fenetre et on l'affiche */ super (titre); setSize (largeur, hauteur) ; add ("South", boutonQuitter) ; boutonQuitter.addActionListener (this) ; addMouseListener (this) ; laPlume = new Plume(this); show () ; /* on cree un offscreen pour y effectuer les affichages */ Dimension offDimension = getSize () ; offImage = createImage(offDimension.width, offDimension.height); offGraphics = offImage.getGraphics () ; offsetX = (getInsets().left + largeur)/2 ; offsetY = (getInsets().top + hauteur)/2 ; offGraphics.translate (offsetX, offsetY) ; } /** * * crée et affiche une fenêtre de dessin "à la logo".
* La Plume associée à la fenêtre est passée en paramètre et doit être créée explicitement. * * @param titre le titre de la fenêtre. * @param largeur largeur de la fenêtre en pixels. * @param hauteur hauteur de la fenetre en pixels. * @param p la Plume à associer à la fenêtre */ public Fenetre (String titre, int largeur, int hauteur, Plume p) { /* on cree la fenetre et on l'affiche */ this(titre,largeur,hauteur); laPlume = p; p.setFenetre(this); repaint(); // tout cela est très sale et mal programmé, mais cela urge !!!! } /** * * Suspend l'exécution de l'appelant * @param x durée de suspension en millisecondes */ public void pause (int x) { try { Thread.sleep(x) ; } catch (InterruptedException signal) { signal.printStackTrace(); System.exit(1); } } /** * Affiche un point. * @param p le point à afficher */ public void affichePoint ( Pt p) { afficheDisque (p, 2) ; } /** * Efface un point. * @param p le point à effacer */ public void effacePoint ( Pt p) { couleurPlume = getForeground () ; offGraphics.setColor (getBackground ()) ; affichePoint (p) ; offGraphics.setColor (couleurPlume) ; } /** * Affiche un cercle. * @param c le centre du cercle * @param r le rayon du cercle */ public void afficheCercle (Pt c, double r) { offGraphics.drawOval ((int) Math.round(c.x-r), -(int) Math.round(c.y-r), (int) Math.round(r*2), (int) Math.round(r*2)) ; repaint () ; } /** * Efface un cercle. * @param c le centre du cercle * @param r le rayon du cercle */ public void effaceCercle (Pt c, double r) { couleurPlume = getForeground () ; offGraphics.setColor (getBackground ()) ; afficheCercle (c, r) ; offGraphics.setColor (couleurPlume) ; } /** * Affiche un disque (cercle plein). * @param c le centre du cercle * @param r le rayon du cercle */ public void afficheDisque (Pt c, double r) { offGraphics.fillOval ((int) Math.round(c.x-r), -(int) Math.round(c.y-r), (int) Math.round(r*2), (int) Math.round(r*2)) ; repaint () ; } /** * Efface un disque. * @param c le centre du cercle * @param r le rayon du cercle */ public void effaceDisque (Pt c, double r) { couleurPlume = getForeground () ; offGraphics.setColor (getBackground ()) ; afficheDisque (c, r) ; offGraphics.setColor (couleurPlume) ; } /** * Affiche un segment. * @param p1 point origine du segment * @param p2 point extremité du segment */ public void afficheSegment ( Pt p1, Pt p2) { offGraphics.drawLine ((int)Math.round(p1.x), (int)Math.round(-p1.y), (int) Math.round(p2.x), (int) Math.round(-p2.y)) ; repaint () ; } /** * Efface un segment. * @param p1 origine du segment * @param p2 extremité du segment */ public void effaceSegment ( Pt p1, Pt p2) { couleurPlume = getForeground () ; offGraphics.setColor (getBackground ()) ; afficheSegment (p1, p2) ; offGraphics.setColor (couleurPlume) ; } /** * * Bloque l'appelant jusqu'à ce qu'un clic souris ait eu lieu * dans la fenetre. * Lorrsqu'un clic est effectué retourne les coordonnées du point correspondant * Le point sur lequel le clic a eu lieu est affiché. * Attention ne marche pas toujours très bien sous Windows (mauvaise gestion des threads ?). * @return le point où était le mulôt au moment du clic. */ public Pt attendsClic () { int mx, my ; // Change le titre du bouton boutonQuitter.setLabel("Cliquez dans la fenetre") ; boutonQuitter.setEnabled(false); repaint () ; // on attends qu'un clic ait lieu clic = false ; attendsClic = true ; while (! clic) { try { Thread.sleep(5) ; } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); } } attendsClic = false ; // Restitue le titre du bouton boutonQuitter.setLabel("Quitter ...") ; boutonQuitter.setEnabled(true); repaint () ; /* on renvoie les coordonnees du point clique */ return (new Pt (clicX, -clicY)) ; } /** * retourne la plume pour dessiner dans la fenêtre * @return reference de l'objet Plume associé à la fenêtre */ public Plume getPlume() { return laPlume; } /** * retourne une chaîne (String) représentant la fenêtre et la plume qu'elle contient. * @return la chaîne représentant la fenêtre.
* "je suis une fenêtre"
* "ma taile : ... ..."
* "je suis une Plume"
* "ma position : x = .. y =.."
* "mon cap : ..."
* "je suis levée" ou "je suis baissée"
*/ public String toString() { return "Je suis une Fenetre\n" + "ma taille " + getSize().width + " " + getSize().height + "\n" + laPlume; } /* ---------------------------------------------------------------- Methodes de gestion de la fenetre ---------------------------------------------------------------- */ public void update (Graphics g) { if (offImage != null) g.drawImage(offImage, 0, 0, this); // on affiche l'offscreen if (laPlume.estVisible()) laPlume.dessineToi(g); } public void paint (Graphics g) { update (g) ; } /* ---------------------------------------------------------------- Methodes de l'interface MouseListener ---------------------------------------------------------------- */ public void mouseClicked (MouseEvent e) { } public void mousePressed (MouseEvent e) { } ; public void mouseEntered (MouseEvent e) { } ; public void mouseReleased (MouseEvent e) { if (attendsClic) { clic = true ; clicX = e.getX() - offsetX ; clicY = e.getY() - offsetY ; } } ; public void mouseExited (MouseEvent e) { } ; /* ---------------------------------------------------------------- Methodes de l'interface ActionListener ---------------------------------------------------------------- */ public void actionPerformed (ActionEvent e) { if (e.getSource() == boutonQuitter) { System.exit (0) ; } ; } /* ---------------------------------------------------------------- Programme de TEST ---------------------------------------------------------------- */ static void main(String[] args) { Fenetre f = new Fenetre("TEST",600,600); Plume laPlume = f.getPlume(); laPlume.avance(50); Pt pt = f.attendsClic(); f.pause(1000); laPlume.tourne(120); laPlume.avance(100); f.pause(300); laPlume.tourne(120); laPlume.avance(100); f.pause(300); laPlume.tourne(120); laPlume.avance(50); f.pause(300); laPlume.positionne(0,-100); laPlume.avance(1000); laPlume.leve(); laPlume.positionne(-50,-60); laPlume.tourne(-45); pt = f.attendsClic(); for (int i = 0; i < 10; i++) { laPlume.baisse(); laPlume.avance(10); laPlume.leve(); laPlume.avance(10); } } }