Licence CC BY-NC-SA

TP : une calculatrice

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Ah ! Ça faisait longtemps… Un petit TP ! Dans celui-ci, nous allons - enfin, vous allez - pouvoir réviser tout ce qui a été vu au cours de cette partie :

  • les fenêtres ;
  • les conteneurs ;
  • les boutons ;
  • les interactions ;
  • les classes internes ;

L'objectif est ici de réaliser une petite calculatrice basique.

Élaboration

Nous allons tout de suite voir ce dont notre calculatrice devra être capable :

  • Effectuer un calcul simple : 12 + 3 par exemple.
  • Faire des calculs à la chaîne, par exemple : 1 + 2 + … ; lorsqu'on clique à nouveau sur un opérateur, il faut afficher le résultat du calcul précédent.
  • Donner la possibilité de tout recommencer à zéro.
  • Gérer l'exception d'une division par 0 !

Conception

Vous devriez obtenir à peu de choses près la figure suivante.

Notre calculatrice

Voyons maintenant ce dont nous avons besoin pour parvenir à nos fins :

  • autant de boutons qu'il en faut ;
  • autant de conteneurs que nécessaire ;
  • un JLabel pour l'affichage ;
  • un booléen pour savoir si un opérateur a été sélectionné ;
  • un booléen pour savoir si nous devons effacer ce qui figure à l'écran et écrire un nouveau nombre ;
  • nous allons utiliser une variable de type double pour nos calculs ;
  • il va nous falloir des classes internes qui implémenteront l'interface ActionListener ;
  • et c'est à peu près tout.

Pour alléger le nombre de classes internes, vous pouvez en créer une qui se chargera d'écrire ce qui doit être affiché à l'écran. Utilisez la méthode getSource() pour savoir sur quel bouton on a cliqué.

Je ne vais pas tout vous dire, il faut que vous cherchiez par vous-mêmes : la réflexion est très importante ! En revanche, vous devez savoir que la correction que je vous fournis n'est pas la correction. Il y a plusieurs solutions possibles. Je vous propose seulement l'une d'elles.

Allez, au boulot !

Correction

Vous avez bien réfléchi ? Vous vous êtes brûlé quelques neurones ? Vous avez mérité votre correction ! Regardez bien comment tout interagit, et vous comprendrez comment fonctionne ce code.

  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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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;

public class Calculatrice extends JFrame {
  private JPanel container = new JPanel();
  //Tableau stockant les éléments à afficher dans la calculatrice
  String[] tab_string = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "=", "C", "+", "-", "*", "/"};
  //Un bouton par élément à afficher
  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 = "";

  public Calculatrice(){
    this.setSize(240, 260);
    this.setTitle("Calculette");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.setResizable(false);
    //On initialise le conteneur avec tous les composants
      initComposant();
      //On ajoute le conteneur
    this.setContentPane(container);
    this.setVisible(true);
  }

  private void initComposant(){
    //On définit la police d'écriture à utiliser
    Font police = new Font("Arial", Font.BOLD, 20);
    ecran = new JLabel("0");
    ecran.setFont(police);
    //On aligne les informations à droite dans le JLabel
    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));

    //On parcourt le tableau initialisé
    //afin de créer nos boutons
    for(int i = 0; i < tab_string.length; i++){
      tab_button[i] = new JButton(tab_string[i]);
      tab_button[i].setPreferredSize(dim);
      switch(i){
        //Pour chaque élément situé à la fin du tableau
        //et qui n'est pas un chiffre
        //on définit le comportement à avoir grâce à un listener
        case 11 :
          tab_button[i].addActionListener(new EgalListener());
          chiffre.add(tab_button[i]);
          break;
        case 12 :
          tab_button[i].setForeground(Color.red);
          tab_button[i].addActionListener(new ResetListener());
          operateur.add(tab_button[i]);
          break;
        case 13 :
          tab_button[i].addActionListener(new PlusListener());
          tab_button[i].setPreferredSize(dim2);
          operateur.add(tab_button[i]);
          break;
        case 14 :
          tab_button[i].addActionListener(new MoinsListener());
          tab_button[i].setPreferredSize(dim2);
          operateur.add(tab_button[i]);
          break;    
        case 15 :   
          tab_button[i].addActionListener(new MultiListener());
          tab_button[i].setPreferredSize(dim2);
          operateur.add(tab_button[i]);
          break;
        case 16 :
          tab_button[i].addActionListener(new DivListener());
          tab_button[i].setPreferredSize(dim2);
          operateur.add(tab_button[i]);
          break;
        default :
          //Par défaut, ce sont les premiers éléments du tableau
          //donc des chiffres, on affecte alors le bon listener
          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);
  }

  //Méthode permettant d'effectuer un calcul selon l'opérateur sélectionné
  private void calcul(){
    if(operateur.equals("+")){
      chiffre1 = chiffre1 + 
            Double.valueOf(ecran.getText()).doubleValue();
      ecran.setText(String.valueOf(chiffre1));
    }
    if(operateur.equals("-")){
      chiffre1 = chiffre1 - 
            Double.valueOf(ecran.getText()).doubleValue();
      ecran.setText(String.valueOf(chiffre1));
    }          
    if(operateur.equals("*")){
      chiffre1 = chiffre1 * 
            Double.valueOf(ecran.getText()).doubleValue();
      ecran.setText(String.valueOf(chiffre1));
    }     
    if(operateur.equals("/")){
      try{
        chiffre1 = chiffre1 / 
              Double.valueOf(ecran.getText()).doubleValue();
        ecran.setText(String.valueOf(chiffre1));
      } catch(ArithmeticException e) {
        ecran.setText("0");
      }
    }
  }

  //Listener utilisé pour les chiffres
  //Permet de stocker les chiffres et de les afficher
  class ChiffreListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      //On affiche le chiffre additionnel dans le label
      String str = ((JButton)e.getSource()).getText();
      if(update){
        update = false;
      }
      else{
        if(!ecran.getText().equals("0"))
          str = ecran.getText() + str;
      }
      ecran.setText(str);
    }
  }

  //Listener affecté au bouton =
  class EgalListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      calcul();
      update = true;
      clicOperateur = false;
    }
  }

  //Listener affecté au bouton +
  class PlusListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      if(clicOperateur){
        calcul();
        ecran.setText(String.valueOf(chiffre1));
      }
      else{
        chiffre1 = Double.valueOf(ecran.getText()).doubleValue();
        clicOperateur = true;
      }
      operateur = "+";
      update = true;
    }
  }

  //Listener affecté au bouton -
  class MoinsListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      if(clicOperateur){
        calcul();
        ecran.setText(String.valueOf(chiffre1));
      }
      else{
        chiffre1 = Double.valueOf(ecran.getText()).doubleValue();
        clicOperateur = true;
      }
      operateur = "-";
      update = true;
    }
  }

  //Listener affecté au bouton *
  class MultiListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      if(clicOperateur){
        calcul();
        ecran.setText(String.valueOf(chiffre1));
      }
      else{
        chiffre1 = Double.valueOf(ecran.getText()).doubleValue();
        clicOperateur = true;
      }
      operateur = "*";
      update = true;
    }
  }

  //Listener affecté au bouton /
  class DivListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      if(clicOperateur){
        calcul();
        ecran.setText(String.valueOf(chiffre1));
      }
      else{
        chiffre1 = Double.valueOf(ecran.getText()).doubleValue();
        clicOperateur = true;
      }
      operateur = "/";
      update = true;
    }
  }

  //Listener affecté au bouton de remise à zéro
  class ResetListener implements ActionListener {
    public void actionPerformed(ActionEvent arg0){
      clicOperateur = false;
      update = true;
      chiffre1 = 0;
      operateur = "";
      ecran.setText("");
    }
  }      
}
1
2
3
4
5
public class Main {
  public static void main(String[] args) {
    Calculatrice calculette = new Calculatrice();
  } 
}

Je vais vous donner une petite astuce afin de créer un .jar exécutable en Java.

Générer un .jar exécutable

Tout d'abord, qu'est-ce qu'un .jar ? C'est une extension propre aux archives Java (Java ARchive). Ce type de fichier contient tout ce dont a besoin la JVM pour lancer un programme. Une fois votre archive créée, il vous suffit de double-cliquer sur celle-ci pour lancer l'application. C'est le meilleur moyen de distribuer votre programme.

C'est exact pour peu que vous ayez ajouté les exécutables de votre JRE (présents dans le répertoire bin) dans votre variable d'environnement PATH ! Si ce n'est pas le cas, refaites un tour dans le premier chapitre du livre, section « Compilation en ligne de commande », et remplacez le répertoire du JDK par celui du JRE (si vous n'avez pas téléchargé le JDK ; sinon, allez récupérer ce dernier).

La création d'un .jar est un jeu d'enfant. Commencez par effectuer un clic droit sur votre projet et choisissez l'option Export, comme le montre la figure suivante.

Exporter son projet

Vous voici dans la gestion des exports. Eclipse vous demande quel type d'export vous souhaitez réaliser, comme à la figure suivante.

Type d'export à choisir

Comme l'illustre la figure précédent, sélectionnez JAR File puis cliquez sur Next. Vous voici maintenant dans la section qui vous demande les fichiers que vous souhaitez inclure dans votre archive, comme à la figure suivante.

Choix des fichiers à inclure

  • Dans le premier cadre, sélectionnez tous les fichiers qui composeront votre exécutable .jar.
  • Dans le second cadre, indiquez à Eclipse l'endroit où créer l'archive et le nom vous souhaitez lui donner.
  • Ensuite, cliquez sur Next.

La page suivante n'est pas très pertinente ; je la mets cependant en figure suivante afin de ne perdre personne.

Choix du niveau d'erreurs tolérable

Cliquez sur Next : vous arrivez sur la page qui vous demande de spécifier l'emplacement de la méthode main dans votre programme (figure suivante).

Choix du point de départ du programme

Cliquez sur Browse… pour afficher un pop-up listant les fichiers des programmes contenant une méthode main. Ici, nous n'en avons qu'une (voir figure suivante). Souvenez-vous qu'il est possible que plusieurs méthodes main soient déclarées, mais une seule sera exécutée !

Notre méthode main

Sélectionnez le point de départ de votre application et validez. La figure suivante correspond à ce que vous devriez obtenir.

Récapitulatif d'export

Vous pouvez maintenant cliquer sur Finish et voir s'afficher un message ressemblant à celui de la figure suivante.

Message lors de l'export

Ce type de message n'est pas alarmant : il vous signale qu'il existe des éléments qu'Eclipse ne juge pas très clairs. Ils n'empêcheront toutefois pas votre application de fonctionner, contrairement à un message d'erreur que vous repérerez facilement : il est en rouge.

Une fois cette étape validée, vous pouvez voir avec satisfaction qu'un fichier .jar a bien été généré dans le dossier spécifié, comme à la figure suivante.

Fichier exécutable .jar

Double-cliquez sur ce fichier : votre calculatrice se lance !