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 Wed, 08 Oct 2014 21:29:23 +0200
34 public class DrawingWindow {
36 /** Largeur de la fenêtre */
37 public final int width;
39 /** Hauteur de la fenêtre */
40 public final int height;
43 * Construit une nouvelle fenêtre de dessin avec le titre et les dimensions
44 * passés en paramètres.
46 * @param title titre de la fenêtre
47 * @param width largeur de la fenêtre
48 * @param height hauteur de la fenêtre
50 * @see javax.swing.JPanel
52 public DrawingWindow(String title, int width, int height) {
54 this.title = new String(title);
58 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
59 graphics = image.createGraphics();
62 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
63 public void run() { createGUI(); }
67 System.err.println("Error: interrupted while creating GUI");
68 System.err.println("Got exception: " + e);
72 setColor(Color.BLACK);
73 setBgColor(Color.WHITE);
79 * Change la couleur de dessin.
81 * @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 * Le nom de couleur est de la forme "black", "white", "red", "blue", ...
97 * @param name nom de couleur
99 * @see #setColor(Color)
100 * @see #setColor(float, float, float)
101 * @see #setBgColor(String)
103 public void setColor(String name) {
105 Field field = Class.forName("java.awt.Color").getField(name);
106 graphics.setColor((Color)field.get(null));
107 } catch (Exception e) {
108 System.err.println("Warning: color not found: " + name);
113 * Change la couleur de dessin.
115 * Les composantes de rouge, vert et bleu de la couleur doivent être
116 * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
117 * du noir; si les trois composantes sont à 1, on obtient du blanc.
119 * @param red composante de rouge
120 * @param green composante de vert
121 * @param blue composante de bleu
123 * @see #setColor(Color)
124 * @see #setColor(String)
125 * @see #setBgColor(float, float, float)
127 public void setColor(float red, float green, float blue) {
128 setColor(new Color(red, green, blue));
132 * Change la couleur de fond.
134 * @param color couleur
136 * @see #setBgColor(String)
137 * @see #setBgColor(float, float, float)
138 * @see #setColor(Color)
141 public void setBgColor(Color color) {
146 * Change la couleur de fond.
148 * @param name nom de couleur
150 * @see #setBgColor(Color)
151 * @see #setBgColor(float, float, float)
152 * @see #setColor(String)
155 public void setBgColor(String name) {
157 Field field = Class.forName("java.awt.Color").getField(name);
158 bgColor = (Color)field.get(null);
159 } catch (Exception e) {
160 System.err.println("Warning: color not found: " + name);
164 /** Change la couleur de fond.
166 * @param red composante de rouge
167 * @param green composante de vert
168 * @param blue composante de bleu
170 * @see #setBgColor(Color)
171 * @see #setBgColor(String)
172 * @see #setColor(float, float, float)
175 public void setBgColor(float red, float green, float blue) {
176 bgColor = new Color(red, green, blue);
182 * La fenêtre est effacée avec la couleur de fond courante.
186 public void clearGraph() {
187 synchronized (image) {
188 Color c = graphics.getColor();
189 graphics.setColor(bgColor);
190 graphics.fillRect(0, 0, width, height);
191 graphics.setColor(c);
196 /** Dessine un point.
198 * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
203 public void drawPoint(int x, int y) {
204 synchronized (image) {
205 image.setRGB(x, y, graphics.getColor().getRGB());
207 panel.repaint(x, y, 1, 1);
211 * Dessine un segment.
213 * Dessine un segement de droite entre les coordonnées (x1, y1) et
214 * (x2, y2), avec la couleur de dessin courante.
218 public void drawLine(int x1, int y1, int x2, int y2) {
219 synchronized (image) {
220 graphics.drawLine(x1, y1, x2, y2);
222 panel.repaint(Math.min(x1, x2), Math.min(y1, y2),
223 Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);
226 /** Dessine un rectangle.
228 * Dessine le rectangle parallèle aux axes et défini par les
229 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
230 * la couleur de dessin courante.
235 public void drawRect(int x1, int y1, int x2, int y2) {
236 int x = Math.min(x1, x2);
237 int y = Math.min(y1, y2);
238 int w = Math.abs(x1 - x2);
239 int h = Math.abs(y1 - y2);
240 synchronized (image) {
241 graphics.drawRect(x, y, w, h);
243 panel.repaint(x, y, w + 1, h + 1);
246 /** Dessine un rectangle plein.
248 * Dessine le rectangle plein parallèle aux axes et défini par les
249 * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
250 * la couleur de dessin courante.
255 public void fillRect(int x1, int y1, int x2, int y2) {
256 int x = Math.min(x1, x2);
257 int y = Math.min(y1, y2);
258 int w = Math.abs(x1 - x2) + 1;
259 int h = Math.abs(y1 - y2) + 1;
260 synchronized (image) {
261 graphics.fillRect(x, y, w, h);
263 panel.repaint(x, y, w, h);
269 * Dessine un cercle de centre (x, y) et de rayon r. Utilise la
270 * couleur de dessin courante.
275 public void drawCircle(int x, int y, int r) {
276 synchronized (image) {
277 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
279 panel.repaint(x - r, y - r, 2 * r + 1, 2 * r + 1);
285 * Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
286 * Utilise la couleur de dessin courante.
291 public void fillCircle(int x, int y, int r) {
292 synchronized (image) {
293 graphics.drawOval(x - r, y - r, 2 * r, 2 * r);
294 graphics.fillOval(x - r, y - r, 2 * r, 2 * r);
296 panel.repaint(x - r, y - r, 2 * r + 1, 2 * r + 1);
302 * Écrit le texte text, aux coordonnées (x, y).
304 public void drawText(int x, int y, String text) {
305 synchronized (image) {
306 graphics.drawString(text, x, y);
308 panel.repaint(); // don't know how to calculate tighter bounding box
312 * Retourne la couleur d'un pixel.
314 * Retourne la couleur du pixel de coordonnées (x, y).
316 * @return couleur du pixel
318 public int getPointColor(int x, int y) {
319 return image.getRGB(x, y);
323 * Synchronise le contenu de la fenêtre.
325 * Pour des raisons d'efficacités, le résultat des fonctions de dessin
326 * n'est pas affiché immédiatement. L'appel à sync permet de
327 * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
328 * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
332 // put an empty action on the event queue, and wait for its completion
334 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
335 public void run() { }
338 catch (Exception e) {
343 * Ferme la fenêtre graphique.
345 public void closeGraph() {
346 javax.swing.SwingUtilities.invokeLater(new Runnable() {
349 new WindowEvent(frame,
350 WindowEvent.WINDOW_CLOSING);
351 Toolkit.getDefaultToolkit()
352 .getSystemEventQueue().postEvent(ev);
359 * Suspend l'exécution pendant un certain temps.
361 * @param secs temps d'attente en seconde
363 static void sleep(long secs) {
365 Thread.sleep(secs * 1000);
367 catch (Exception e) {
372 * Suspend l'exécution pendant un certain temps.
374 * @param msecs temps d'attente en millisecondes
376 static void msleep(long msecs) {
380 catch (Exception e) {
385 * Suspend l'exécution pendant un certain temps.
387 * @param usecs temps d'attente en microsecondes
389 static void usleep(long usecs) {
391 Thread.sleep(usecs / 1000, (int)(usecs % 1000) * 1000);
393 catch (Exception e) {
397 /* PRIVATE STUFF FOLLOWS */
399 private final String title; // window's title
400 private JFrame frame; // the frame (window)
401 private DWPanel panel; // the panel showing the image
402 private BufferedImage image; // the image we draw into
403 private Graphics2D graphics; // graphics associated with image
404 private Color bgColor; // background color, for clearGraph()
406 // To be run on the Event Dispatching Thread
408 panel = new DWPanel(this);
410 frame = new JFrame(title);
413 frame.setResizable(false);
414 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
415 frame.addKeyListener(panel);
416 frame.setLocationByPlatform(true);
417 frame.setVisible(true);
420 private class DWPanel extends JPanel implements KeyListener {
422 private static final long serialVersionUID = 0;
424 final DrawingWindow w;
426 DWPanel(DrawingWindow w) {
428 Dimension dimension = new Dimension(w.width, w.height);
429 super.setMinimumSize(dimension);
430 super.setMaximumSize(dimension);
431 super.setPreferredSize(dimension);
434 public void paint(Graphics g) {
435 synchronized (w.image) {
436 g.drawImage(w.image, 0, 0, null);
440 public void keyPressed(KeyEvent e) {
441 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
446 public void keyReleased(KeyEvent e) { }
447 public void keyTyped(KeyEvent e) { }