Nous voilà partis pour un nouveau TP.
Dans celui-ci, ce qui prime c'est surtout :
- d'utiliser les menus, les accélérateurs et mnémoniques ;
- d'ajouter une barre d'outils ;
- de créer des implémentations et savoir les utiliser sur plusieurs composants ;
- d'utiliser des classes anonymes ;
- ...
Je ne vous demande pas de faire un logiciel hyper-pointu !

Vous constaterez d'ailleurs qu'il peut y avoir des bugs d'affichage... Je ne vous dis pas lesquels, on ne sait jamais, si vous ne les trouvez pas...
Ce n'est pas tout ça mais... si on commençait ?
Voilà les recommandations.
Vous devez faire une sorte d'ardoise magique. En gros, celle-ci devra être composée d'un
JPanel amélioré (ça sent l'héritage...) sur lequel vous pourrez tracer des choses en cliquant et en déplaçant la souris.
Vos tracés devront être effectués point par point, ceux-ci d'une taille que je vous laisse apprécier. Par contre, vous devrez pouvoir utiliser deux sortes de "
pinceaux" :
Vous aurez aussi la possibilité de changer la couleur de vos traits, les couleurs que j'ai choisies sont :
- le bleu ;
- le rouge ;
- le vert.
Il faut
OBLIGATOIREMENT :
- un menu avec accélérateurs et mnémoniques ;
- une barre d'outils avec les formes et les couleurs ;
- un menu "Quitter" et un menu "Effacer" ;
- que les formes et les couleurs soient accessibles via le menu !
Voici ce que j'ai obtenu :
Et voilà ce que j'ai fait rien que pour vous :
Attention : vous allez utiliser la méthode repaint()
de votre composant ; cependant, souvenez-vous que celle-ci est appelée automatiquement lors du redimensionnement de votre fenêtre, de la réduction, de l'agrandissement... Vous allez devoir gérer ce cas de figure ! Sinon, votre zone de dessin s'effacera à chaque redimensionnement !
Je vous conseille de créer une classe
Point qui va contenir les informations relatives à un point tracé (couleur, taille, position...).
Il va falloir que vous gériez une collection de points (générique, la collection

) dans votre classe dérivée de
JPanel !
J'en ai presque trop dit...
Bon, je suis un ange aujourd'hui.

Voici les images que j'ai utilisées :
Je sais... Elles ne sont pas terribles.

Mais le but n'est pas là !
Avant de vous lancer dans votre code, vous devez savoir quelques choses...
Afin que vous puissiez faire des tracés, vous allez devoir détecter le mouvement de votre souris.
Je ne vous ai pas encore parlé de ça auparavant, mais vous avez l'habitude d'utiliser des interfaces de gestion d'événements, maintenant...
Afin de détecter les mouvements de votre souris, vous allez devoir utiliser l'interface
MouseMotionListener ; celle-ci contient deux méthodes :
- mouseMoved(MouseEvent e) : détecte le mouvement de la souris sur le composant ;
- mouseDragged(MouseEvent e) : idem que ci-dessus mais vous devrez avoir cliqué sur le composant et maintenir ce clic enfoncé pendant le mouvement (exactement ce qu'il vous faut
).
Voilà : vous allez devoir créer une implémentation de cette interface pour réussir à dessiner sur votre conteneur !
Bon ! Ne vous hâtez pas trop, réfléchissez bien à ce dont vous avez besoin. Comment utiliser vos implémentations... Bref, surtout ne pas vous précipiter !
Un code bien réfléchi est un code rapidement opérationnel !
C'est à vous, maintenant...
À vos claviers.
Roulement de tambour... C'est le moment de vérité !
J'ai mis des images sur mes boutons de barre d'outils...
Secret (cliquez pour afficher)
Point.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 | import java.awt.Color;
public class Point {
//Couleur du point
private Color color = Color.red;
//Taille
private int size = 10;
//position sur l'axe X : initialisé au dehors du conteneur
private int x = -10;
//Position sur l'axe Y : initialisé au dehors du conteneur
private int y = -10;
//Type de point
private String type = "ROND";
/**
* Constructeur par défaut
*/
public Point(){}
/**
* Constructeur avec paramètres
* @param x
* @param y
* @param size
* @param color
* @param type
*/
public Point(int x, int y, int size, Color color, String type){
this.size = size;
this.x = x;
this.y = y;
this.color = color;
this.type = type;
}
//****************************************
// ACCESSEURS
//****************************************
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
|
DrawPanel.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 | import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
//Couleur du pointeur
private Color pointerColor = Color.red;
//Forme du pointeur
private String pointerType = "CIRCLE";
//Position X du pointeur
private int posX = -10, oldX = -10;
//Position Y du pointeur
private int posY = -10, oldY = -10;
//pour savoir si on doit dessiner ou non
private boolean erasing = true;
//Taille du pointeur
private int pointerSize = 15;
//Collection de points !
private ArrayList<Point> points = new ArrayList<Point>();
/**
* Constructeur
*/
public DrawPanel(){
this.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
points.add(new Point(e.getX() - (pointerSize / 2), e.getY() - (pointerSize / 2), pointerSize, pointerColor, pointerType));
repaint();
}
});
this.addMouseMotionListener(new MouseMotionListener(){
public void mouseDragged(MouseEvent e) {
//On récupère les coordonnées de la souris
//et on enlève la moitié de la taille du pointeur
//pour centrer le tracé
points.add(new Point(e.getX() - (pointerSize / 2), e.getY() - (pointerSize / 2), pointerSize, pointerColor, pointerType));
repaint();
}
public void mouseMoved(MouseEvent e) {}
});
}
/**
* Vous la connaissez maintenant, celle-là ;)
*/
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
//Si on doit effacer, on ne passe pas dans le else => pas de dessin
if(this.erasing){
this.erasing = false;
}
else{
//On parcourt notre collection de points
for(Point p : this.points)
{
//On récupère la couleur
g.setColor(p.getColor());
//Selon le type de point
if(p.getType().equals("SQUARE")){
g.fillRect(p.getX(), p.getY(), p.getSize(), p.getSize());
}
else{
g.fillOval(p.getX(), p.getY(), p.getSize(), p.getSize());
}
}
}
}
/**
* Efface le contenu
*/
public void erase(){
this.erasing = true;
this.points = new ArrayList<Point>();
repaint();
}
/**
* Définit la couleur du pointeur
* @param c
*/
public void setPointerColor(Color c){
this.pointerColor = c;
}
/**
* Définit la forme du pointeur
* @param str
*/
public void setPointerType(String str){
this.pointerType = str;
}
}
|
Fenetre.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 | import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
public class Fenetre extends JFrame {
//**************************************
// LE MENU
//**************************************
private JMenuBar menuBar = new JMenuBar();
JMenu fichier = new JMenu("Fichier"),
edition = new JMenu("Edition"),
forme = new JMenu("Forme du pointeur"),
couleur = new JMenu("Couleur du pointeur");
JMenuItem nouveau = new JMenuItem("Effacer"),
quitter = new JMenuItem("Quitter"),
rond = new JMenuItem("Rond"),
carre = new JMenuItem("Carré"),
bleu = new JMenuItem("Bleu"),
rouge = new JMenuItem("Rouge"),
vert = new JMenuItem("Vert");
//****************************************
// LA BARRE D'OUTILS
//****************************************
JToolBar toolBar = new JToolBar();
JButton square = new JButton(new ImageIcon("images/carré.jpg")),
circle = new JButton(new ImageIcon("images/rond.jpg")),
red = new JButton(new ImageIcon("images/rouge.jpg")),
green = new JButton(new ImageIcon("images/vert.jpg")),
blue = new JButton(new ImageIcon("images/bleu.jpg"));
//***************************************
// LES ÉCOUTEURS
//***************************************
private FormeListener fListener = new FormeListener();
private CouleurListener cListener = new CouleurListener();
//Notre zone de dessin
private DrawPanel drawPanel = new DrawPanel();
public Fenetre(){
this.setSize(700, 500);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//On initialise le menu
this.initMenu();
//Idem pour la barre d'outils
this.initToolBar();
//On positionne notre zone de dessin
this.getContentPane().add(drawPanel, BorderLayout.CENTER);
this.setVisible(true);
}
/**
* Initialise le menu
*/
private void initMenu(){
nouveau.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
drawPanel.erase();
}
});
nouveau.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK));
quitter.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
quitter.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK));
fichier.add(nouveau);
fichier.addSeparator();
fichier.add(quitter);
fichier.setMnemonic('F');
carre.addActionListener(fListener);
rond.addActionListener(fListener);
forme.add(rond);
forme.add(carre);
rouge.addActionListener(cListener);
vert.addActionListener(cListener);
bleu.addActionListener(cListener);
couleur.add(rouge);
couleur.add(vert);
couleur.add(bleu);
edition.setMnemonic('E');
edition.add(forme);
edition.addSeparator();
edition.add(couleur);
menuBar.add(fichier);
menuBar.add(edition);
this.setJMenuBar(menuBar);
}
/**
* Initialise l barre d'outils
*/
private void initToolBar(){
JPanel panneau = new JPanel();
square.addActionListener(fListener);
circle.addActionListener(fListener);
red.addActionListener(cListener);
green.addActionListener(cListener);
blue.addActionListener(cListener);
toolBar.add(square);
toolBar.add(circle);
toolBar.addSeparator();
toolBar.add(red);
toolBar.add(blue);
toolBar.add(green);
this.getContentPane().add(toolBar, BorderLayout.NORTH);
}
//ÉCOUTEUR POUR LE CHANGEMENT DE FORME
//************************************
class FormeListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(e.getSource().getClass().getName().equals("javax.swing.JMenuItem")){
if(e.getSource()==carre)drawPanel.setPointerType("SQUARE");
else drawPanel.setPointerType("CIRCLE");
}
else{
if(e.getSource()==square)drawPanel.setPointerType("SQUARE");
else drawPanel.setPointerType("CIRCLE");
}
}
}
//ÉCOUTEUR POUR LE CHANGEMENT DE COULEUR
//**************************************
class CouleurListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.out.println(e.getSource().getClass().getName());
if(e.getSource().getClass().getName().equals("javax.swing.JMenuItem")){
System.out.println("OK !");
if(e.getSource()==vert)drawPanel.setPointerColor(Color.green);
else if(e.getSource()==bleu)drawPanel.setPointerColor(Color.blue);
else drawPanel.setPointerColor(Color.red);
}
else{
if(e.getSource()==green)drawPanel.setPointerColor(Color.green);
else if(e.getSource()==blue)drawPanel.setPointerColor(Color.blue);
else drawPanel.setPointerColor(Color.red);
}
}
}
public static void main(String[] args){
Fenetre fen = new Fenetre();
}
}
|
Vous avez pu voir que c'est un code assez simple. Il n'y a rien de difficile et surtout, il a le mérite de vous faire travailler un peu tout ce que vous avez vu jusqu'ici...
Comme je vous l'ai dit dans l'introduction, ce code n'est pas parfait et il n'avait pas vocation à l'être... Je sais que vous êtes assez calés en Java pour avoir ajouté plus de fonctionnalités que moi sur ce TP. Mon code est une solution, ET NON PAS LA SOLUTION.
Voici ce que vous pouvez faire afin de rendre cette application plus attractive :
- permettre de changer la taille du pinceau ;
- avoir une plus grande palette de couleurs ;
- avoir des pinceaux supplémentaires ;
- créer une gomme ;
- ...
Vous voyez que ce ne sont pas les idées qui manquent...
Vous pouvez essayer de faire ce TP avec ces suppléments. Prenez ça comme une version plus difficile du TP, et encore...
Bon. Nous sommes à la fin de ce TP. Retour au tuto.
Même s'il n'est pas parfait, ce TP était tout de même marrant à faire...
Bon, la récréation est finie.
Je sais que certains Zér0s ont une envie folle de créer des menus comme "
Enregistrer" ou "
Enregistrer sous...".
Mais, avant d'en arriver là, nous allons devoir aborder
Les flux d'entrée / de sortie !