5 import java.awt.event.*;
6 import java.awt.image.*;
8 import java.lang.reflect.*;
13 * <p>Cette classe permet d'écrire des applications graphiques simples
14 * en dessinant dans une fenêtre.
16 * <p><b>NB.</b> Pour toutes les méthodes de dessin, le coin en haut à
17 * gauche de la fenêtre a les coordonnées (0, 0). Le coin en bas à
18 * droite de la fenêtre a les coordonnées (largeur - 1, hauteur - 1),
19 * si la fenêtre est de dimension largeur × hauteur.
21 * <p>Un appui sur la touche <Esc> provoque la fermeture de la
22 * fenêtre. Comme pour la plupart des applications, il est également
23 * possible de fermer la fenêtre via le gestionnaire de fenêtres.
25 * <p>Télécharger le code: <a href="DrawingWindow.java">DrawingWindow.java</a>
27 * <p>Télécharger les exemples d'utilisation:
28 * <a href="Hello.java">Hello.java</a>
29 * <a href="Exemple1.java">Exemple1.java</a>
30 * <a href="Exemple2.java">Exemple2.java</a>
31 * <a href="Exemple3.java">Exemple3.java</a>
33 * @author Arnaud Giersch <arnaud.giersch@univ-fcomte.fr>
36 public class DrawingWindow
38 implements KeyListener {
40 /** Titre de la fenêtre */
41 public final String title;
43 /** Largeur de la fenêtre */
44 public final int width;
46 /** Hauteur de la fenêtre */
47 public final int height;
50 * Construit une nouvelle fenêtre de dessin avec le titre et les dimensions
51 * passés en paramètres.
53 * @param title titre de la fenêtre
54 * @param width largeur de la fenêtre
55 * @param height hauteur de la fenêtre
57 * @see javax.swing.JPanel
59 public DrawingWindow(String title, int width, int height) {
60 this.title = new String(title);
64 Dimension dimension = new Dimension(width, height);
65 super.setMinimumSize(dimension);
66 super.setMaximumSize(dimension);
67 super.setPreferredSize(dimension);
69 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
70 graphics = image.createGraphics();
72 setColor(Color.BLACK);
73 setBgColor(Color.WHITE);
77 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
79 frame = new JFrame(DrawingWindow.this.title);
81 frame.add(DrawingWindow.this);
83 frame.setResizable(false);
85 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
86 frame.addKeyListener(DrawingWindow.this);
88 frame.setLocationByPlatform(true);
89 frame.setVisible(true);
94 System.err.println("Warning: caught spurious exception: " + e);
100 * Change la couleur de dessin.
102 * @param color couleur
104 * @see java.awt.Color
105 * @see #setColor(String)
106 * @see #setColor(float, float, float)
107 * @see #setBgColor(Color)
109 public void setColor(Color color) {
110 graphics.setColor(color);
114 * Change la couleur de dessin.
116 * Le nom de couleur est de la forme "black", "white", "red", "blue", ...
118 * @param name nom de couleur
120 * @see #setColor(Color)
121 * @see #setColor(float, float, float)
122 * @see #setBgColor(String)
124 public void setColor(String name) {
126 Field field = Class.forName("java.awt.Color").getField(name);
127 graphics.setColor((Color)field.get(null));
128 } catch (Exception e) {
129 System.err.println("Warning: color not found: " + name);
134 * Change la couleur de dessin.
136 * Les composantes de rouge, vert et bleu de la couleur doivent être
137 * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
138 * du noir; si les trois composantes sont à 1, on obtient du blanc.
140 * @param red composante de rouge
141 * @param green composante de vert
142 * @param blue composante de bleu
144 * @see #setColor(Color)
145 * @see #setColor(String)
146 * @see #setBgColor(float, float, float)
148 public void setColor(float red, float green, float blue) {
149 setColor(new Color(red, green, blue));
153 * Change la couleur de fond.
155 * @param color couleur
157 * @see #setBgColor(String)
158 * @see #setBgColor(float, float, float)
159 * @see #setColor(Color)
162 public void setBgColor(Color color) {
167 * Change la couleur de fond.
169 * @param name nom de couleur
171 * @see #setBgColor(Color)
172 * @see #setBgColor(float, float, float)
173 * @see #setColor(String)
176 public void setBgColor(String name) {
178 Field field = Class.forName("java.awt.Color").getField(name);
179 bgColor = (Color)field.get(null);
180 } catch (Exception e) {
181 System.err.println("Warning: color not found: " + name);
185 /** Change la couleur de fond.
187 * @param red composante de rouge
188 * @param green composante de vert
189 * @param blue composante de bleu
191 * @see #setBgColor(Color)
192 * @see #setBgColor(String)
193 * @see #setColor(float, float, float)
196 public void setBgColor(float red, float green, float blue) {
197 bgColor = new Color(red, green, blue);
203 * La fenêtre est effacée avec la couleur de fond courante.
207 public void clearGraph() {
208 synchronized (image) {
209 Color c = graphics.getColor();
210 graphics.setColor(bgColor);
211 graphics.fillRect(0, 0, width, height);
212 graphics.setColor(c);
217 /** Dessine un point.
219 * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
224 public void drawPoint(int x, int y) {
225 synchronized (image) {
226 image.setRGB(x, y, graphics.getColor().getRGB());
232 * Dessine un segment.
234 * Dessine un segement de droite entre les coordonnées (x1, y1) et
235 * (x2, y2), avec la couleur de dessin courante.
239 public void drawLine(int x1, int y1, int x2, int y2) {
240 synchronized (image) {
241 graphics.drawLine(x1, y1, x2, y2);
243 repaint(Math.min(x1, x2), Math.min(y1, y2),
244 Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);
247 /** Dessine un rectangle.
249 * Dessine le rectangle parallèle aux axes et défini par les
250 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
251 * la couleur de dessin courante.
256 public void drawRect(int x1, int y1, int x2, int y2) {
257 int x = Math.min(x1, x2);
258 int y = Math.min(y1, y2);
259 int w = Math.abs(x1 - x2);
260 int h = Math.abs(y1 - y2);
261 synchronized (image) {
262 graphics.drawRect(x, y, w, h);
267 /** Dessine un rectangle plein.
269 * Dessine le rectangle plein parallèle aux axes et défini par les
270 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
271 * la couleur de dessin courante.
276 public void fillRect(int x1, int y1, int x2, int y2) {
277 int x = Math.min(x1, x2);
278 int y = Math.min(y1, y2);
279 int w = Math.abs(x1 - x2);
280 int h = Math.abs(y1 - y2);
281 synchronized (image) {
282 graphics.fillRect(x, y, w, h);
290 * Dessine un cercle de centre (x, y) et de rayon r. Utilise la
291 * couleur de dessin courante.
296 public void drawCircle(int x, int y, int r) {
297 synchronized (image) {
298 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
300 repaint(x - r, y - r, 2 * r, 2 * r);
306 * Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
307 * Utilise la couleur de dessin courante.
312 public void fillCircle(int x, int y, int r) {
313 synchronized (image) {
314 graphics.fillOval(x - r, y - r, 2 * r, 2 * r);
316 repaint(x - r, y - r, 2 * r, 2 * r);
322 * Écrit le texte text, aux coordonnées (x, y).
324 public void drawText(int x, int y, String text) {
325 synchronized (image) {
326 graphics.drawString(text, x, y);
328 repaint(); // don't know how to calculate tighter bounding box
332 * Retourne la couleur d'un pixel.
334 * Retourne la couleur du pixel de coordonnées (x, y).
336 * @return couleur du pixel
338 public int getPointColor(int x, int y) {
339 return image.getRGB(x, y);
343 * Synchronise le contenu de la fenêtre.
345 * Pour des raisons d'efficacités, le résultat des fonctions de dessin
346 * n'est pas affiché immédiatement. L'appel à sync permet de
347 * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
348 * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
352 // put an empty action on the event queue, and wait for its completion
354 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
355 public void run() { }
358 catch (Exception e) {
363 * Ferme la fenêtre graphique.
365 public void closeGraph() {
366 javax.swing.SwingUtilities.invokeLater(new Runnable() {
369 new WindowEvent(frame,
370 WindowEvent.WINDOW_CLOSING);
371 Toolkit.getDefaultToolkit()
372 .getSystemEventQueue().postEvent(ev);
379 * Suspend l'exécution pendant un certain temps.
381 * @param secs temps d'attente en seconde
383 static void sleep(long secs) {
385 Thread.sleep(secs * 1000);
387 catch (Exception e) {
392 * Suspend l'exécution pendant un certain temps.
394 * @param msecs temps d'attente en millisecondes
396 static void msleep(long msecs) {
400 catch (Exception e) {
405 * Suspend l'exécution pendant un certain temps.
407 * @param usecs temps d'attente en microsecondes
409 static void usleep(long usecs) {
411 Thread.sleep(usecs / 1000, (int)(usecs % 1000) * 1000);
413 catch (Exception e) {
417 public void paint(Graphics g) {
418 synchronized (image) {
419 g.drawImage(image, 0, 0, null);
423 public void keyPressed(KeyEvent e) {
424 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
429 public void keyReleased(KeyEvent e) { }
430 public void keyTyped(KeyEvent e) { }
432 /* PRIVATE STUFF FOLLOW */
434 private static final long serialVersionUID = 0;
436 private JFrame frame;
437 private BufferedImage image;
438 private Graphics2D graphics;
439 private Color bgColor;