Auteurs: Vincent Padovani, Jean-Baptiste Yunès
L'objectif de cette séance de travaux pratiques du cours d'interfaces graphiques est de réaliser un mini logiciel de dessin afin d'expérimenter (entre autres) la gestion d'événements. Ce TP est prévu pour durer deux séances.
Comme d'habitude on procédera par petite touches. Pour commencer on écrira
un programme permettant de suivre la souris et de
dessiner la courbe suivie.
Ensuite on ajoutera la possibilité de changer la couleur du crayon.
On permettra de conserver l'image alors même qu'elle pourrait être recouverte
par d'autres fenêtres ou d'autres événements du même type.
Pour terminer on essaiera de sauver l'image produite dans un fichier,
d'autoriser à relire l'image contenue dans un fichier, etc...
On veut créer une application très primitive permettant de dessiner sur une zone de l'écran comme dans l'image qui suit:
Un tracé sera obtenu en maintenant le bouton de la souris appuyé, puis en
déplaçant celle-ci à volonté, le tracé s'interrompant lorsque le bouton de
la souris est relâché. Le tracé devra être continu : si l'utilisateur
déplace rapidement la souris d'un point à un autre, les deux positions
successives lues seront non adjacentes, mais devront être reliées par un
segment. Le dessin se fera dans un composant vierge dont la
classe Ardoise
sera définie comme une extension de la classe java.awt.Canvas
. La classe
Ardoise
devra implémenter l'interface
javax.swing.event.MouseInputListener
(cette interface n'est qu'une combinaison des deux
interfaces java.awt.event.MouseListener
et java.awt.event.MouseMotionListener
). Elle pourra contenir les
champs suivants :
DEF_WIDTH
et DEF_HEIGHT
représentant les
dimensions par défaut de l'ardoiseDEF_COLOR
représentant la couleur par
défaut du crayonjava.awt.geom.Point2D
(ou java.awt.Point
)
représentant les deux dernières
positions connues de la souris (cf. java.awt.event.MouseEvent
),
c'est-à-dire les extrémités du dernier segment non encore tracé. Noter que
dans le cas d'un évènement de type mousePressed
, ces deux positions devront
toutes deux prendre la valeur de la position courante, de manière à tracer
un point.La classe Ardoise
hérite d'autre part des deux méthodes suivantes. La première devra être réimplémentée :
void paint(Graphics g)
où g est de
classe java.awt.Graphics
. Cette
méthode est invoquée soit par la méthode void update(Graphics g)
. Cette méthode est invoquée
par AWT après chaque invocation de la méthode repaint()
ci-dessous. Son
implémentation par défaut effectue d'abord un effacement complet du composant,
puis une invocation de paint sur le même contexte graphique. Elle n'est jamais
invoquée de manière directe. Tant que vous n'aurez pas implémenté la
sauvegarde hors-écran du contenu de l'ardoise, il vous faudra surcharger cette
méthode en remplaçant son implémentation par l'unique
invocation paint(g)
, de manière à éviter l'effacement du composant entre deux tracés de segments par
paint
.
void repaint()
: c'est cette méthode que l'on doit invoquer à
chaque fois que l'on souhaite voir invoquée, le plus tôt possible, la
méthode précédente.On essaiera de ne pas utiliser d'appel à setSize()
mais d'être
conforme au protocole de calcul des tailles des composants
(preferredSize()
).
On voudrait ajouter à l'application précédente la possibilité de changer la couleur du crayon, pour obtenir des images comme:
On ajoutera donc un javax.swing.JButton qui déclenchera l'apparition d'un javax.swing.JDialog modal contenant un JColorChooser. La couleur choisie sera alors utilisée pour changer la couleur courante du crayon et la couleur du bouton.
On ajoutera à l'application précédente de quoi assurer qu'en toutes circonstances l'image dessinée à l'écran n'est pas perdue (en essayant de la masquer par une autre fenêtre, en iconifiant, en retaillant, etc). Pour cela il est conseillé d'utiliser soit de sauvegarder toutes les actions réalisées (un peu lourd mais intéressant) ou d'utiliser une image dans laquelle dessiner et à faire apparaître à l'écran lorsque c'est nécessaire (on choisira alors une java.awt.Image.BufferedImage).
On complètera l'application de façon à ajouter des menus permettant de lire/sauver l'image dans divers formats disponibles. La consultation de la classe javax.imageio.ImageIO devrait aider. On veillera à ne pas quitter l'application sans avoir sauvé l'image sans confirmer (voir la classe javax.swing.JDialog). On pourra imaginer pouvoir retailler l'image, etc.
S'il vous reste quelques minutes, vous pouvez finir de réécrire ?!@!shop ou &!@imp mais en mieux (pensez tout de même à finir votre année de Master).