Voici le plus facile à développer et celui que vous devez maîtriser le mieux...
Nous allons créer celui-ci avec le package
javax.swing
. Vous devriez maintenant avoir l'habitude de créer des IHM, mais si vous ne voulez pas répéter ce que vous avez déjà fait, vous pouvez récupérer mon code d'IHM de calculatrice dans le
TP correspondant.
Il va de soi que, vu que les traitements sont tous dans cette classe, nous allons enlever un grand nombre de classes internes !
Je vous donne donc le code source de notre classe que j'ai mis dans le package
com.sdz.vue
.
Calculette.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 | package com.sdz.vue;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import com.sdz.controler.*;
import com.sdz.observer.Observer;
public class Calculette extends JFrame implements Observer{
private JPanel container = new JPanel();
String[] tab_string = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "=", "C", "+", "-", "*", "/"};
JButton[] tab_button = new JButton[tab_string.length];
private JLabel ecran = new JLabel();
private Dimension dim = new Dimension(50, 40);
private Dimension dim2 = new Dimension(50, 31);
private double chiffre1;
private boolean clicOperateur = false, update = false;
private String operateur = "";
//Notre instance de notre objet contrôleur
private AbstractControler controler;
public Calculette(AbstractControler controler){
this.setSize(240, 260);
this.setTitle("Calculette");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setResizable(false);
initComposant();
this.controler = controler;
this.setContentPane(container);
this.setVisible(true);
}
private void initComposant(){
Font police = new Font("Arial", Font.BOLD, 20);
ecran = new JLabel("0");
ecran.setFont(police);
ecran.setHorizontalAlignment(JLabel.RIGHT);
ecran.setPreferredSize(new Dimension(220, 20));
JPanel operateur = new JPanel();
operateur.setPreferredSize(new Dimension(55, 225));
JPanel chiffre = new JPanel();
chiffre.setPreferredSize(new Dimension(165, 225));
JPanel panEcran = new JPanel();
panEcran.setPreferredSize(new Dimension(220, 30));
//Nous utiliserons le même listener pour tous les opérateurs
OperateurListener opeListener = new OperateurListener();
for(int i = 0; i < tab_string.length; i++)
{
tab_button[i] = new JButton(tab_string[i]);
tab_button[i].setPreferredSize(dim);
switch(i){
case 11 :
tab_button[i].addActionListener(opeListener);
chiffre.add(tab_button[i]);
break;
case 12 :
tab_button[i].setForeground(Color.red);
tab_button[i].addActionListener(new ResetListener());
tab_button[i].setPreferredSize(dim2);
operateur.add(tab_button[i]);
break;
case 13 :
case 14 :
case 15 :
case 16 :
tab_button[i].setForeground(Color.red);
tab_button[i].addActionListener(opeListener);
tab_button[i].setPreferredSize(dim2);
operateur.add(tab_button[i]);
break;
default :
chiffre.add(tab_button[i]);
tab_button[i].addActionListener(new ChiffreListener());
break;
}
}
panEcran.add(ecran);
panEcran.setBorder(BorderFactory.createLineBorder(Color.black));
container.add(panEcran, BorderLayout.NORTH);
container.add(chiffre, BorderLayout.CENTER);
container.add(operateur, BorderLayout.EAST);
}
//**********************************************
// LES LISTENERS POUR NOS BOUTONS
//**********************************************
class ChiffreListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
//On affiche le chiffre en plus dans le label
String str = ((JButton)e.getSource()).getText();
if(!ecran.getText().equals("0"))
str = ecran.getText() + str;
controler.setNombre(((JButton)e.getSource()).getText());
}
}
class OperateurListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
controler.setOperateur(((JButton)e.getSource()).getText());
}
}
class ResetListener implements ActionListener{
public void actionPerformed(ActionEvent arg0) {
controler.reset();
}
}
//************************************************
// IMPLEMENTATION DU PATTERN OBSERVER
//************************************************
public void update(String str) {
ecran.setText(str);
}
}
|
Vous devez être à même de comprendre ce code vu qu'il ressemble beaucoup à notre calculette faite dans le TP de la partie 3...

Il y a une nouveauté toutefois, une instance de notre contrôleur ! Celui-ci, je le rappelle, sera la strategy de notre vue...
Notre classe devra donc inclure une instance de notre implémentation du pattern strategy : vous pouvez voir celle-ci juste avant le constructeur de notre classe.
Voilà, toutes nos classes sont opérationnelles.
Il ne nous manque plus qu'une classe de test afin de voir le résultat...
La voici :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | import com.sdz.controler.*;
import com.sdz.model.*;
import com.sdz.vue.Calculette;
public class Main {
public static void main(String[] args) {
//Instanciation de notre modèle
AbstractModel calc = new Calculator();
//création du contrôleur
AbstractControler controler = new CalculetteControler(calc);
//Création de notre fenêtre avec le contrôleur en paramètre
Calculette calculette = new Calculette(controler);
//Ajout de la fenêtre comme observer de notre modèle
calc.addObserver(calculette);
}
}
|
Testez ce code et le tout fonctionne très bien !
Tous nos objets sont inter-connectés et dialoguent facilement.
Vu que vous connaissez la façon de travailler de ce pattern, nous allons décortiquer ce qu'il se passe.
Lorsque vous cliquez sur un chiffre
- L'action est envoyée au contrôleur.
- Celui-ci vérifie si le chiffre est conforme.
- Il informe le modèle.
- Celui-ci est mis à jour et informe la vue de ses changements.
- Celle-ci rafraîchit son affichage.
Lorsque vous cliquez sur un opérateur
- L'action est toujours envoyée au contrôleur.
- Celui-ci vérifie si l'opérateur envoyé est dans sa liste.
- Le cas échéant, il informe le modèle.
- Celui-ci agit en conséquence et informe la vue de son changement.
- La vue est mise à jour...
La même chose se passe lorsque nous cliquerons sur le bouton "
reset".
Voilà une bonne chose de faite !
Nous aurions très bien pu faire la même chose sans le contrôleur !
Oui, bien sûr. Même sans modèle !
Rappelez-vous du pourquoi de l'existence des DP :
prévenir des modifications de codes !
Avec une telle architecture, vous pourrez modifier indépendamment l'un des trois composants de ce pattern.
Si vous ne voulez plus de nombres à virgules à l'affichage mais uniquement des entiers, vous pouvez créer un autre modèle qui ne travaille que sur des entiers !
De même, si vous voulez bloquer certains chiffres ou certains opérateurs, il vous suffit de coder une autre classe héritant de
AbstractControler qui, elle, ne laissera pas passer tel ou tel choix utilisateur !
Je ne vous donne pas d'exemple pour la vue, nous avons déjà abordé cela dans le chapitre sur le pattern observer.

Oh et puis si, tenez ! C'est encore un des exemples les plus simples qu'on puisse faire...
Au lieu de gérer l'affichage dans notre classe
Calculette, nous allons créer une classe
Ecran, toujours dans notre package
com.sdz.vue
, dans laquelle nous allons afficher tout ce que nous renvoie le modèle !
Voici cette classe.
Ecran.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 | package com.sdz.vue;
import java.awt.*;
import javax.swing.*;
import com.sdz.observer.Observer;
public class Ecran extends JFrame implements Observer{
private JLabel ecran = new JLabel();
public Ecran(Component c){
this.setSize(300, 100);
this.setLocationRelativeTo(c);
this.setResizable(false);
Font police = new Font("DS-digital", Font.BOLD, 50);
this.ecran.setFont(police);
this.ecran.setHorizontalAlignment(JLabel.RIGHT);
this.getContentPane().add(this.ecran, BorderLayout.CENTER);
this.setVisible(true);
}
public void update(String str) {
ecran.setText(str);
}
}
|
Et voici notre nouveau code de test :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | import com.sdz.controler.AbstractControler;
import com.sdz.controler.CalculetteControler;
import com.sdz.model.AbstractModel;
import com.sdz.model.Calculator;
import com.sdz.vue.Calculette;
import com.sdz.vue.Ecran;
public class Main {
public static void main(String[] args) {
AbstractModel calc = new Calculator();
AbstractControler controler = new CalculetteControler(calc);
Calculette calculette = new Calculette(controler);
//On crée notre Ecran
Ecran ecran = new Ecran(calculette);
//On informe que c'est l'instance d'écran qui écoutera notre modèle
calc.addObserver(ecran);
}
}
|
Et le résultat :
Vous pouvez aussi séparer les chiffres des opérateurs... Enfin, faire ce que vous voulez, quoi...
Avant de terminer ce chapitre, vous devez savoir encore quelques choses...
Ce pattern est aussi utilisé lorsque vous développez avec la plateforme J
EE et, pour être tout à fait honnête, il en est même le principe de base !