2 import java.awt.event.*;
3 import java.awt.image.*;
5 import java.lang.reflect.*;
10 * <p>Cette classe permet d'écrire des applications graphiques simples
11 * en dessinant dans une fenêtre.
13 * <p><b>NB.</b> Pour toutes les méthodes de dessin, le coin en haut à
14 * gauche de la fenêtre a les coordonnées (0, 0). Le coin en bas à
15 * droite de la fenêtre a les coordonnées (largeur - 1, hauteur - 1),
16 * si la fenêtre est de dimension largeur × hauteur.
18 * <p>Un appui sur la touche <Esc> provoque la fermeture de la
19 * fenêtre. Comme pour la plupart des applications, il est également
20 * possible de fermer la fenêtre via le gestionnaire de fenêtres.
22 * <p>Télécharger le code: <a href="DrawingWindow.java">DrawingWindow.java</a>
24 * <p>Télécharger des exemples d'utilisation:
25 * <a href="Hello.java">Hello.java</a>
26 * <a href="Exemple1.java">Exemple1.java</a>
27 * <a href="Exemple2.java">Exemple2.java</a>
28 * <a href="Exemple3.java">Exemple3.java</a>
30 * @author Arnaud Giersch <arnaud.giersch@univ-fcomte.fr>
33 public class DrawingWindow
35 implements KeyListener {
37 /** Titre de la fenêtre */
38 public final String title;
40 /** Largeur de la fenêtre */
41 public final int width;
43 /** Hauteur de la fenêtre */
44 public final int height;
47 * Construit une nouvelle fenêtre de dessin avec le titre et les dimensions
48 * passés en paramètres.
50 * @param title titre de la fenêtre
51 * @param width largeur de la fenêtre
52 * @param height hauteur de la fenêtre
54 * @see javax.swing.JPanel
56 public DrawingWindow(String title, int width, int height) {
57 this.title = new String(title);
61 Dimension dimension = new Dimension(width, height);
62 super.setMinimumSize(dimension);
63 super.setMaximumSize(dimension);
64 super.setPreferredSize(dimension);
66 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
67 graphics = image.createGraphics();
69 setColor(Color.BLACK);
70 setBgColor(Color.WHITE);
74 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
76 frame = new JFrame(DrawingWindow.this.title);
78 frame.add(DrawingWindow.this);
80 frame.setResizable(false);
82 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
83 frame.addKeyListener(DrawingWindow.this);
85 frame.setLocationByPlatform(true);
86 frame.setVisible(true);
91 System.err.println("Warning: caught spurious exception: " + e);
97 * Change la couleur de dessin.
99 * @param color couleur
101 * @see java.awt.Color
102 * @see #setColor(String)
103 * @see #setColor(float, float, float)
104 * @see #setBgColor(Color)
106 public void setColor(Color color) {
107 graphics.setColor(color);
111 * Change la couleur de dessin.
113 * Le nom de couleur est de la forme "black", "white", "red", "blue", ...
115 * @param name nom de couleur
117 * @see #setColor(Color)
118 * @see #setColor(float, float, float)
119 * @see #setBgColor(String)
121 public void setColor(String name) {
123 Field field = Class.forName("java.awt.Color").getField(name);
124 graphics.setColor((Color)field.get(null));
125 } catch (Exception e) {
126 System.err.println("Warning: color not found: " + name);
131 * Change la couleur de dessin.
133 * Les composantes de rouge, vert et bleu de la couleur doivent être
134 * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
135 * du noir; si les trois composantes sont à 1, on obtient du blanc.
137 * @param red composante de rouge
138 * @param green composante de vert
139 * @param blue composante de bleu
141 * @see #setColor(Color)
142 * @see #setColor(String)
143 * @see #setBgColor(float, float, float)
145 public void setColor(float red, float green, float blue) {
146 setColor(new Color(red, green, blue));
150 * Change la couleur de fond.
152 * @param color couleur
154 * @see #setBgColor(String)
155 * @see #setBgColor(float, float, float)
156 * @see #setColor(Color)
159 public void setBgColor(Color color) {
164 * Change la couleur de fond.
166 * @param name nom de couleur
168 * @see #setBgColor(Color)
169 * @see #setBgColor(float, float, float)
170 * @see #setColor(String)
173 public void setBgColor(String name) {
175 Field field = Class.forName("java.awt.Color").getField(name);
176 bgColor = (Color)field.get(null);
177 } catch (Exception e) {
178 System.err.println("Warning: color not found: " + name);
182 /** Change la couleur de fond.
184 * @param red composante de rouge
185 * @param green composante de vert
186 * @param blue composante de bleu
188 * @see #setBgColor(Color)
189 * @see #setBgColor(String)
190 * @see #setColor(float, float, float)
193 public void setBgColor(float red, float green, float blue) {
194 bgColor = new Color(red, green, blue);
200 * La fenêtre est effacée avec la couleur de fond courante.
204 public void clearGraph() {
205 synchronized (image) {
206 Color c = graphics.getColor();
207 graphics.setColor(bgColor);
208 graphics.fillRect(0, 0, width, height);
209 graphics.setColor(c);
214 /** Dessine un point.
216 * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
221 public void drawPoint(int x, int y) {
222 synchronized (image) {
223 image.setRGB(x, y, graphics.getColor().getRGB());
229 * Dessine un segment.
231 * Dessine un segement de droite entre les coordonnées (x1, y1) et
232 * (x2, y2), avec la couleur de dessin courante.
236 public void drawLine(int x1, int y1, int x2, int y2) {
237 synchronized (image) {
238 graphics.drawLine(x1, y1, x2, y2);
240 repaint(Math.min(x1, x2), Math.min(y1, y2),
241 Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);
244 /** Dessine un rectangle.
246 * Dessine le rectangle parallèle aux axes et défini par les
247 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
248 * la couleur de dessin courante.
253 public void drawRect(int x1, int y1, int x2, int y2) {
254 int x = Math.min(x1, x2);
255 int y = Math.min(y1, y2);
256 int w = Math.abs(x1 - x2);
257 int h = Math.abs(y1 - y2);
258 synchronized (image) {
259 graphics.drawRect(x, y, w, h);
264 /** Dessine un rectangle plein.
266 * Dessine le rectangle plein parallèle aux axes et défini par les
267 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
268 * la couleur de dessin courante.
273 public void fillRect(int x1, int y1, int x2, int y2) {
274 int x = Math.min(x1, x2);
275 int y = Math.min(y1, y2);
276 int w = Math.abs(x1 - x2);
277 int h = Math.abs(y1 - y2);
278 synchronized (image) {
279 graphics.fillRect(x, y, w, h);
287 * Dessine un cercle de centre (x, y) et de rayon r. Utilise la
288 * couleur de dessin courante.
293 public void drawCircle(int x, int y, int r) {
294 synchronized (image) {
295 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
297 repaint(x - r, y - r, 2 * r, 2 * r);
303 * Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
304 * Utilise la couleur de dessin courante.
309 public void fillCircle(int x, int y, int r) {
310 synchronized (image) {
311 graphics.fillOval(x - r, y - r, 2 * r, 2 * r);
313 repaint(x - r, y - r, 2 * r, 2 * r);
319 * Écrit le texte text, aux coordonnées (x, y).
321 public void drawText(int x, int y, String text) {
322 synchronized (image) {
323 graphics.drawString(text, x, y);
325 repaint(); // don't know how to calculate tighter bounding box
329 * Retourne la couleur d'un pixel.
331 * Retourne la couleur du pixel de coordonnées (x, y).
333 * @return couleur du pixel
335 public int getPointColor(int x, int y) {
336 return image.getRGB(x, y);
340 * Synchronise le contenu de la fenêtre.
342 * Pour des raisons d'efficacités, le résultat des fonctions de dessin
343 * n'est pas affiché immédiatement. L'appel à sync permet de
344 * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
345 * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
349 // put an empty action on the event queue, and wait for its completion
351 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
352 public void run() { }
355 catch (Exception e) {
360 * Ferme la fenêtre graphique.
362 public void closeGraph() {
363 javax.swing.SwingUtilities.invokeLater(new Runnable() {
366 new WindowEvent(frame,
367 WindowEvent.WINDOW_CLOSING);
368 Toolkit.getDefaultToolkit()
369 .getSystemEventQueue().postEvent(ev);
376 * Suspend l'exécution pendant un certain temps.
378 * @param secs temps d'attente en seconde
380 static void sleep(long secs) {
382 Thread.sleep(secs * 1000);
384 catch (Exception e) {
389 * Suspend l'exécution pendant un certain temps.
391 * @param msecs temps d'attente en millisecondes
393 static void msleep(long msecs) {
397 catch (Exception e) {
402 * Suspend l'exécution pendant un certain temps.
404 * @param usecs temps d'attente en microsecondes
406 static void usleep(long usecs) {
408 Thread.sleep(usecs / 1000, (int)(usecs % 1000) * 1000);
410 catch (Exception e) {
414 public void paint(Graphics g) {
415 synchronized (image) {
416 g.drawImage(image, 0, 0, null);
420 public void keyPressed(KeyEvent e) {
421 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
426 public void keyReleased(KeyEvent e) { }
427 public void keyTyped(KeyEvent e) { }
429 /* PRIVATE STUFF FOLLOW */
431 private static final long serialVersionUID = 0;
433 private JFrame frame;
434 private BufferedImage image;
435 private Graphics2D graphics;
436 private Color bgColor;