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>
31 * @version Mon Oct 13 15:20:17 2014 +0200
33 public class DrawingWindow {
35 /** Largeur de la fenêtre */
36 public final int width;
38 /** Hauteur de la fenêtre */
39 public final int height;
42 * Construit une nouvelle fenêtre de dessin avec le titre et les dimensions
43 * passés en paramètres.
45 * @param title titre de la fenêtre
46 * @param width largeur de la fenêtre
47 * @param height hauteur de la fenêtre
49 * @see javax.swing.JPanel
51 public DrawingWindow(String title, int width, int height) {
53 this.title = new String(title);
57 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
58 graphics = image.createGraphics();
61 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
62 public void run() { createGUI(); }
66 System.err.println("Error: interrupted while creating GUI");
67 System.err.println("Got exception: " + e);
71 setColor(Color.BLACK);
72 setBgColor(Color.WHITE);
78 * Change la couleur de dessin.
80 * @param color couleur
84 * @see #setColor(String)
85 * @see #setColor(float, float, float)
86 * @see #setBgColor(Color)
88 public void setColor(Color color) {
89 graphics.setColor(color);
93 * Change la couleur de dessin.
95 * La couleur est un entier, tel que retourné par {@link #getPointColor}.
96 * Normalement de la forme #00RRGGBB.
100 * @see #setColor(String)
101 * @see #setColor(float, float, float)
102 * @see #setBgColor(int)
103 * @see #getPointColor
105 public void setColor(int rgb) {
106 setColor(new Color(rgb));
110 * Change la couleur de dessin.
112 * Le nom de couleur peut être "black", "blue", "cyan",
113 * "darkGray", "gray", "green", "lightGray", "magenta", "orange",
114 * "pink", "red", "white", ou "yellow".
116 * @param name nom de couleur
118 * @see #setColor(int)
119 * @see #setColor(float, float, float)
120 * @see #setBgColor(String)
122 public void setColor(String name) {
124 Field field = Class.forName("java.awt.Color").getField(name);
125 graphics.setColor((Color)field.get(null));
126 } catch (Exception e) {
127 System.err.println("Warning: color not found: " + name);
132 * Change la couleur de dessin.
134 * Les composantes de rouge, vert et bleu de la couleur doivent être
135 * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
136 * du noir; si les trois composantes sont à 1, on obtient du blanc.
138 * @param red composante de rouge
139 * @param green composante de vert
140 * @param blue composante de bleu
142 * @see #setColor(int)
143 * @see #setColor(String)
144 * @see #setBgColor(float, float, float)
146 public void setColor(float red, float green, float blue) {
147 setColor(new Color(red, green, blue));
151 * Change la couleur de fond.
153 * @param color couleur
155 * @see #setBgColor(int)
156 * @see #setBgColor(String)
157 * @see #setBgColor(float, float, float)
158 * @see #setColor(Color)
161 public void setBgColor(Color color) {
165 /** Change la couleur de fond.
169 * @see #setBgColor(String)
170 * @see #setBgColor(float, float, float)
171 * @see #setColor(int)
172 * @see #getPointColor
175 public void setBgColor(int rgb) {
176 bgColor = new Color(rgb);
180 * Change la couleur de fond.
182 * @param name nom de couleur
184 * @see #setBgColor(int)
185 * @see #setBgColor(float, float, float)
186 * @see #setColor(String)
189 public void setBgColor(String name) {
191 Field field = Class.forName("java.awt.Color").getField(name);
192 bgColor = (Color)field.get(null);
193 } catch (Exception e) {
194 System.err.println("Warning: color not found: " + name);
198 /** Change la couleur de fond.
200 * @param red composante de rouge
201 * @param green composante de vert
202 * @param blue composante de bleu
204 * @see #setBgColor(int)
205 * @see #setBgColor(String)
206 * @see #setColor(float, float, float)
209 public void setBgColor(float red, float green, float blue) {
210 bgColor = new Color(red, green, blue);
216 * La fenêtre est effacée avec la couleur de fond courante.
220 public void clearGraph() {
221 synchronized (image) {
222 Color c = graphics.getColor();
223 graphics.setColor(bgColor);
224 graphics.fillRect(0, 0, width, height);
225 graphics.setColor(c);
230 /** Dessine un point.
232 * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
237 public void drawPoint(int x, int y) {
238 synchronized (image) {
239 image.setRGB(x, y, graphics.getColor().getRGB());
241 panel.repaint(x, y, 1, 1);
245 * Dessine un segment.
247 * Dessine un segement de droite entre les coordonnées (x1, y1) et
248 * (x2, y2), avec la couleur de dessin courante.
252 public void drawLine(int x1, int y1, int x2, int y2) {
253 synchronized (image) {
254 graphics.drawLine(x1, y1, x2, y2);
256 panel.repaint(Math.min(x1, x2), Math.min(y1, y2),
257 Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);
260 /** Dessine un rectangle.
262 * Dessine le rectangle parallèle aux axes et défini par les
263 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
264 * la couleur de dessin courante.
269 public void drawRect(int x1, int y1, int x2, int y2) {
270 int x = Math.min(x1, x2);
271 int y = Math.min(y1, y2);
272 int w = Math.abs(x1 - x2);
273 int h = Math.abs(y1 - y2);
274 synchronized (image) {
275 graphics.drawRect(x, y, w, h);
277 panel.repaint(x, y, w + 1, h + 1);
280 /** Dessine un rectangle plein.
282 * Dessine le rectangle plein parallèle aux axes et défini par les
283 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
284 * la couleur de dessin courante.
289 public void fillRect(int x1, int y1, int x2, int y2) {
290 int x = Math.min(x1, x2);
291 int y = Math.min(y1, y2);
292 int w = Math.abs(x1 - x2) + 1;
293 int h = Math.abs(y1 - y2) + 1;
294 synchronized (image) {
295 graphics.fillRect(x, y, w, h);
297 panel.repaint(x, y, w, h);
303 * Dessine un cercle de centre (x, y) et de rayon r. Utilise la
304 * couleur de dessin courante.
309 public void drawCircle(int x, int y, int r) {
310 synchronized (image) {
311 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
313 panel.repaint(x - r, y - r, 2 * r + 1, 2 * r + 1);
319 * Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
320 * Utilise la couleur de dessin courante.
325 public void fillCircle(int x, int y, int r) {
326 synchronized (image) {
327 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
328 graphics.fillOval(x - r, y - r, 2 * r, 2 * r);
330 panel.repaint(x - r, y - r, 2 * r + 1, 2 * r + 1);
334 * Dessine un triangle.
336 * Dessine un triangle défini par les coordonnées de ses sommets:
337 * (x1, y1), (x2, y2) et (x3, y3). Utilise la couleur de dessin
344 public void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
345 Polygon poly = new Polygon();
346 poly.addPoint(x1, y1);
347 poly.addPoint(x2, y2);
348 poly.addPoint(x3, y3);
349 synchronized (image) {
350 graphics.drawPolygon(poly);
352 panel.repaint(poly.getBounds());
356 * Dessine un triangle plein.
358 * Dessine un triangle plein défini par les coordonnées de ses
359 * sommets: (x1, y1), (x2, y2) et (x3, y3). Utilise la couleur de
365 public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
366 Polygon poly = new Polygon();
367 poly.addPoint(x1, y1);
368 poly.addPoint(x2, y2);
369 poly.addPoint(x3, y3);
370 synchronized (image) {
371 graphics.drawPolygon(poly);
372 graphics.fillPolygon(poly);
374 panel.repaint(poly.getBounds());
380 * Écrit le texte text, aux coordonnées (x, y).
382 public void drawText(int x, int y, String text) {
383 synchronized (image) {
384 graphics.drawString(text, x, y);
386 panel.repaint(); // don't know how to calculate tighter bounding box
390 * Retourne la couleur d'un pixel.
392 * Retourne la couleur du pixel de coordonnées (x, y).
394 * @return couleur du pixel
396 * @see #setColor(int)
397 * @see #setBgColor(int)
399 public int getPointColor(int x, int y) {
400 return image.getRGB(x, y);
404 * Synchronise le contenu de la fenêtre.
406 * Pour des raisons d'efficacités, le résultat des fonctions de dessin
407 * n'est pas affiché immédiatement. L'appel à sync permet de
408 * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
409 * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
413 // put an empty action on the event queue, and wait for its completion
415 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
416 public void run() { }
419 catch (Exception e) {
424 * Ferme la fenêtre graphique.
426 public void closeGraph() {
427 javax.swing.SwingUtilities.invokeLater(new Runnable() {
430 new WindowEvent(frame,
431 WindowEvent.WINDOW_CLOSING);
432 Toolkit.getDefaultToolkit()
433 .getSystemEventQueue().postEvent(ev);
440 * Suspend l'exécution pendant un certain temps.
442 * @param secs temps d'attente en seconde
444 static void sleep(long secs) {
446 Thread.sleep(secs * 1000);
448 catch (Exception e) {
453 * Suspend l'exécution pendant un certain temps.
455 * @param msecs temps d'attente en millisecondes
457 static void msleep(long msecs) {
461 catch (Exception e) {
466 * Suspend l'exécution pendant un certain temps.
468 * @param usecs temps d'attente en microsecondes
470 static void usleep(long usecs) {
472 Thread.sleep(usecs / 1000, (int)(usecs % 1000) * 1000);
474 catch (Exception e) {
478 /* PRIVATE STUFF FOLLOWS */
480 private final String title; // window's title
481 private JFrame frame; // the frame (window)
482 private DWPanel panel; // the panel showing the image
483 private BufferedImage image; // the image we draw into
484 private Graphics2D graphics; // graphics associated with image
485 private Color bgColor; // background color, for clearGraph()
487 // To be run on the Event Dispatching Thread
489 panel = new DWPanel(this);
491 frame = new JFrame(title);
494 frame.setResizable(false);
495 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
496 frame.addKeyListener(panel);
497 frame.setLocationByPlatform(true);
498 frame.setVisible(true);
501 private class DWPanel extends JPanel implements KeyListener {
503 private static final long serialVersionUID = 0;
505 final DrawingWindow w;
507 DWPanel(DrawingWindow w) {
509 Dimension dimension = new Dimension(w.width, w.height);
510 super.setMinimumSize(dimension);
511 super.setMaximumSize(dimension);
512 super.setPreferredSize(dimension);
515 public void paint(Graphics g) {
516 synchronized (w.image) {
517 g.drawImage(w.image, 0, 0, null);
521 public void keyPressed(KeyEvent e) {
522 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
527 public void keyReleased(KeyEvent e) { }
528 public void keyTyped(KeyEvent e) { }