LECON 311

 Les boîtes de dialogue
Les boîtes de dialogue, c'est sûr, vous connaissez !
Cependant, afin d'être sûr que nous parlons de la même chose, voici un petit descriptif.

Une boîte de dialogue est une mini-fenêtre pouvant servir à plusieurs choses :
  • afficher une information (message d'erreur, warning...) ;
  • demander une validation, une réfutation ou une annulation ;
  • demander à l'utilisateur de saisir une information dont le système a besoin ;
  • ...


Vous pouvez voir que ces dernières peuvent servir à beaucoup de choses.
Il faut toutefois les utiliser avec parcimonie : il est, au final, assez pénible qu'une application ouvre une boîte de dialogue à chaque notification, car toute boîte ouverte doit être fermée !

Pour ce point je vous laisse seuls juges de leur utilisation... Et si nous commencions ?
Sommaire du chapitre :

  • Les boîtes d'information
  • Les boîtes de confirmation
  • Les boîtes de saisie
  • Des boîtes de dialogue personnalisées
  • Ce qu'il faut retenir

Les boîtes d'information


L'objet que nous allons utiliser tout au long de ce chapitre n'est autre que le JOptionPane.
Objet assez complexe au premier abord, mais fort pratique.

Voici à quoi ressemblent des boîtes de dialogues "informatives" :


Ces boîtes n'ont pas vocation à participer à de quelconques traitements, elles affichent juste un message pour l'utilisateur.

Voici le code utilisé pour obtenir ces boîtes :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
//Déclaration des objets
 JOptionPane jop1, jop2, jop3;
 
//Boîte du message d'information
//-------------------------------
jop1 = new JOptionPane();
jop1.showMessageDialog(null, "Message informatif", "Information", JOptionPane.INFORMATION_MESSAGE);
               
//Boîte du message préventif
//-------------------------------
jop2 = new JOptionPane();
jop2.showMessageDialog(null, "Message préventif", "Attention", JOptionPane.WARNING_MESSAGE);
               
//Boîte du message d'erreur
//-------------------------------
jop3 = new JOptionPane();
jop3.showMessageDialog(null, "Message d'erreur", "Erreur", JOptionPane.ERROR_MESSAGE);

Ces trois boîtes ne s'affichent pas en même temps...
Pourquoi ça ?

Tout simplement parce qu'en Java, mais aussi dans les autres langages, les boîtes de dialogue sont dites modales.
Ceci signifie que lorsque qu'une boîte fait son apparition, celle-ci bloque toute interaction possible avec un autre composant que ceux présents sur la boîte. Ceci, tant que l'utilisateur n'a pas mis fin au dialogue !

Même en créant un thread différent par boîte de dialogue, vous ne pourrez pas toutes les voir !
Les 3 boîtes seront créées, mais les boîtes s'affichant au centre de la fenêtre, vous ne pourrez en voir que deux sur trois, en déplaçant la première.

Comme le montre le résultat de ce code, vous ne pourrez pas déplacer la deuxième boîte à cause de la modalité des boîtes :

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
import javax.swing.JOptionPane;
 
public class Test {
 
        public static void main(String[] args) {
                                
               Thread t = new Thread(new Runnable(){
                       public void run(){
                               JOptionPane jop1 = new JOptionPane();
                               jop1.showMessageDialog(null, "Message informatif", "Information", JOptionPane.INFORMATION_MESSAGE);             
                       }
               });
               
               Thread t2 = new Thread(new Runnable(){
                       public void run(){
                               JOptionPane jop2 = new JOptionPane();
                               jop2.showMessageDialog(null, "Message préventif", "Attention", JOptionPane.WARNING_MESSAGE);
                       }
               });
               
               Thread t3 = new Thread(new Runnable(){
                       public void run(){
                               JOptionPane jop3 = new JOptionPane();
                               jop3.showMessageDialog(null, "Message d'erreur", "Erreur", JOptionPane.ERROR_MESSAGE);                          
                       }
               });
                       
               t.start();
               t2.start();
               t3.start();
        }
}


Ce qui nous donnerait (tout dépend de l'ordonnanceur, vu qu'il y a trois thread...) :


Maintenant, voyons de plus près la façon de construire un tel objet. Ici nous avons utilisé la méthode : showMessageDialog(Component parentComponent, String message, String title, int messageType); .
  • ComponentparentComponent : correspond au composant parent ; ici, il n'y en a aucun, nous mettons donc null.
  • Stringmessage : permet de renseigner le message à afficher dans la boîte de dialogue.
  • Stringtitle : permet de donner un titre à notre objet.
  • intmessageType : permet de savoir s'il s'agit d'un message d'information, de prévention ou d'erreur. Vous avez sans doute remarqué que, mis à part le texte et le titre, seul ce champ change entre les trois objets !


Il existe deux autres méthodes showMessageDialog() pour cet objet : une qui prend deux paramètres en moins (le titre et le type de message), et une qui prend un paramètre en plus (l'icône à utiliser).

Je pense qu'il est inutile de détailler la méthode avec les paramètres en moins, mais voici des exemples de boîtes avec des icônes définies par nos soins...

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
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
 
 
public class Test {
 
        public static void main(String[] args) {
               
               JOptionPane jop1, jop2, jop3;
               
               jop1 = new JOptionPane();
               ImageIcon img = new ImageIcon("images/information.png");
               jop1.showMessageDialog(null, "Message informatif", "Information", JOptionPane.INFORMATION_MESSAGE, img);
               
               jop2 = new JOptionPane();
               img = new ImageIcon("images/warning.png");
               jop2.showMessageDialog(null, "Message préventif", "Attention", JOptionPane.WARNING_MESSAGE, img);
               
               jop3 = new JOptionPane();
               img = new ImageIcon("images/erreur.png");
               jop3.showMessageDialog(null, "Message d'erreur", "Erreur", JOptionPane.ERROR_MESSAGE, img);                             
 
        }
}

Les images ont été trouvées sur Google puis rangées dans un dossier "images" à la racine du projet Eclipse ! Je vous invite à télécharger vos propres images et de faire vos propres tests...

Vous constaterez aussi l'utilisation de l'objet ImageIcon qui va lire le fichier image à l'emplacement spécifié dans son constructeur.

Voici le résultat obtenu :


Ce type de boîtes est très utile pour notifier à l'utilisateur qu'un traitement s'est terminé ou qu'une erreur est survenue...
L'exemple le plus simple qui me vient en tête serait une division par zéro :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import javax.swing.JOptionPane;
 
public class Test {
 
        public static void main(String[] args) {
               
               int i = 100, j = 0;
               
               try{
                       System.out.println("Résultat = " + (i/j));
               }catch(ArithmeticException ex){
                       JOptionPane  jop3 = new JOptionPane();
                       jop3.showMessageDialog(null, "Division par zéro détecté !", "Erreur fatale ! ! ", JOptionPane.ERROR_MESSAGE);
               }              
        }
}

Les types de boîtes



Voici les types de boîtes que vous pouvez utiliser (valable pour tout ce qui suit), triés par ordre alphabétique s'il vous plaît...:
  • JOptionPane.ERROR_MESSAGE
  • JOptionPane.INFORMATION_MESSAGE
  • JOptionPane.PLAIN_MESSAGE
  • JOptionPane.QUESTION_MESSAGE
  • JOptionPane.WARNING_MESSAGE

Je pense que vous devez mieux voir l'utilité de telles boîtes de dialogues...
Nous allons donc poursuivre avec les boîtes de confirmation.

Les boîtes de confirmation

Comme leur nom l'indique, ces dernières permettent de valider, de réfuter ou d'annuler une décision.
Nous utiliserons toujours l'objet JOptionPane mais, cette fois, avec la méthode showConfirmDialog() . Cette méthode retourne un entier qui correspond à l'option que vous aurez choisie dans cette boîte :
  • Yes ;
  • No ;
  • Cancel.


Comme exemple, nous pouvons prendre notre animation comme nous l'avons laissée la dernière fois.
Nous pourrions utiliser une boîte de confirmation lorsque nous cliquerons sur l'un des boutons contrôlant l'animation (Go ou Stop).

Pour ceux qui n'auraient pas conservé leur projet, voici la classe Panneau :
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class Panneau extends JPanel {

        private int posX = -50;
    private int posY = -50;
    private int drawSize = 50;
    //boolean pour le mode morphing et pour savoir si la taille doit réduire
    private boolean morph = false, reduce = false;;
    private String forme = "ROND";
    //Le compteur de rafraîchissements
    private int increment = 0;
   
    public void paintComponent(Graphics g){
            g.setColor(Color.white);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.red);
            //Si le mode morphing est activé, on peint le morphing
            if(this.morph)
                drawMorph(g);
            //sinon, mode normal
            else
                draw(g);      
    }

    private void draw(Graphics g){
       
        if(this.forme.equals("ROND")){
                g.fillOval(posX, posY, 50, 50);
        }
        if(this.forme.equals("CARRE")){
                g.fillRect(posX, posY, 50, 50);
        }
        if(this.forme.equals("TRIANGLE")){
                
                int s1X = posX + 50/2;
                int s1Y = posY;
                int s2X = posX + 50;
                int s2Y = posY + 50;
                int s3X = posX;
                int s3Y = posY + 50;
               
                int[] ptsX = {s1X, s2X, s3X};
                int[] ptsY = {s1Y, s2Y, s3Y};
               
                g.fillPolygon(ptsX, ptsY, 3);
        }
        if(this.forme.equals("ETOILE")){
               
                int s1X = posX + 50/2;
                int s1Y = posY;
                int s2X = posX + 50;
                int s2Y = posY + 50;                   
                g.drawLine(s1X, s1Y, s2X, s2Y);
               
                int s3X = posX;
                int s3Y = posY + 50/3;
                g.drawLine(s2X, s2Y, s3X, s3Y);
               
                int s4X = posX + 50;
                int s4Y = posY + 50/3;
                g.drawLine(s3X, s3Y, s4X, s4Y);                
                                
                int s5X = posX;
                int s5Y = posY + 50;
                g.drawLine(s4X, s4Y, s5X, s5Y);                
                g.drawLine(s5X, s5Y, s1X, s1Y); 
        }
       
    }
   
    /**
     * Méthode qui peint le morphing
     * @param g
     */
    private void drawMorph(Graphics g){
        //On incrémente le tour
        increment++;
        //On regarde si on doit réduire ou non
        if(drawSize >= 50)reduce = true;
        if(drawSize <= 10)reduce = false;
       
        if(reduce)
                drawSize = drawSize - getUsedSize();
        else
                drawSize = drawSize + getUsedSize();
       
        if(this.forme.equals("ROND")){
                g.fillOval(posX, posY, drawSize, drawSize);
        }
        if(this.forme.equals("CARRE")){
                g.fillRect(posX, posY, drawSize, drawSize);
        }
        if(this.forme.equals("TRIANGLE")){
                 
                int s1X = posX + drawSize/2;
                int s1Y = posY;
                int s2X = posX + drawSize;
                int s2Y = posY + drawSize;
                int s3X = posX;
                int s3Y = posY + drawSize;
               
                int[] ptsX = {s1X, s2X, s3X};
                int[] ptsY = {s1Y, s2Y, s3Y};
               
                g.fillPolygon(ptsX, ptsY, 3);
        }
        if(this.forme.equals("ETOILE")){
               
                int s1X = posX + drawSize/2;
                int s1Y = posY;
                int s2X = posX + drawSize;
                int s2Y = posY + drawSize;             
                g.drawLine(s1X, s1Y, s2X, s2Y);
               
                int s3X = posX;
                int s3Y = posY + drawSize/3;
                g.drawLine(s2X, s2Y, s3X, s3Y);
               
                int s4X = posX + drawSize;
                int s4Y = posY + drawSize/3;
                g.drawLine(s3X, s3Y, s4X, s4Y);                
                               
                int s5X = posX;
                int s5Y = posY + drawSize;
                g.drawLine(s4X, s4Y, s5X, s5Y);                
                g.drawLine(s5X, s5Y, s1X, s1Y); 
        }
       
       
    }
   
    /**
     * Méthode qui retourne le nombre à retrancher (ou ajouter) pour le morphing
     * @return res
     */
    private int getUsedSize(){
        int res = 0;
        //Si le nombre de tours est de 10
        //On réinitialise l'incrément et on retourne 1
        if(increment / 10 == 1){
                increment = 0;
                res = 1;
        }      
        return res;
    }
   
    public int getDrawSize(){
        return drawSize;
    }
   
    public boolean isMorph(){
        return morph;
    }
   
    public void setMorph(boolean bool){
        this.morph = bool;
        //On réinitialise la taille
        drawSize = 50;
    }
   
    public void setForme(String form){
        this.forme = form;
    }
   
    public int getPosX() {
            return posX;
    }

    public void setPosX(int posX) {
            this.posX = posX;
    }

    public int getPosY() {
            return posY;
    }

    public void setPosY(int posY) {
            this.posY = posY;
    }
}

Voici le code de notre classe Fenetre :

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
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
 
public class Fenetre extends JFrame{
 
        private Panneau pan = new Panneau();
        private JButton bouton = new JButton("Go");
        private JButton bouton2 = new JButton("Stop");
    private JPanel container = new JPanel();
    private JLabel label = new JLabel("Choix de la forme");
    private int compteur = 0;
    private boolean animated = true;
    private boolean backX, backY;
    private int x,y ;
    private Thread t;
    private JComboBox combo = new JComboBox();
    
    private JCheckBox morph = new JCheckBox("Morphing");
    
    public Fenetre(){
           
            this.setTitle("Animation");
            this.setSize(300, 300);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLocationRelativeTo(null);
 
            container.setBackground(Color.white);
            container.setLayout(new BorderLayout());
            container.add(pan, BorderLayout.CENTER);
            
            bouton.addActionListener(new BoutonListener());             
            bouton2.addActionListener(new Bouton2Listener());
            
            bouton2.setEnabled(false);
            
            JPanel south = new JPanel();
            south.add(bouton);
            south.add(bouton2);
            container.add(south, BorderLayout.SOUTH);
            
            combo.addItem("ROND");
            combo.addItem("CARRE");
            combo.addItem("TRIANGLE");
            combo.addItem("ETOILE");            
            combo.addActionListener(new FormeListener());
            
            morph.addActionListener(new MorphListener());
            
            JPanel top = new JPanel();
            top.add(label);
            top.add(combo);
            top.add(morph);
            
            container.add(top, BorderLayout.NORTH);
            this.setContentPane(container);
            this.setVisible(true);            
                        
    }
        
    
        private void go(){
               x = pan.getPosX();
               y = pan.getPosY();
        while(this.animated){
               //System.out.println("OK");
               //Si le mode morphing est activé, on utilise la taille actuelle de la forme
               if(pan.isMorph())
               {
                       if(x < 1)backX = false;
                    if(x > pan.getWidth() - pan.getDrawSize())backX = true;               
                    if(y < 1)backY = false;
                    if(y > pan.getHeight() - pan.getDrawSize())backY = true;
               }
               //Sinon, comme d'habitude
               else
               {
                       if(x < 1)backX = false;
                    if(x > pan.getWidth()-50)backX = true;               
                    if(y < 1)backY = false;
                    if(y > pan.getHeight()-50)backY = true;
               }  
            
               if(!backX)pan.setPosX(++x);
            else pan.setPosX(--x);
            if(!backY) pan.setPosY(++y);
            else pan.setPosY(--y);
            pan.repaint();
 
            try {
                    Thread.sleep(3);
            } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
        }       
        }
 
        public class BoutonListener implements ActionListener{
 
               public void actionPerformed(ActionEvent arg0) {
                       
                       JOptionPane jop = new JOptionPane();                  
                       int option = jop.showConfirmDialog(null, "Voulez-vous lancer l'animation ?", "Lancement de l'animation", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                       
                       if(option == JOptionPane.OK_OPTION)
                       {
                               animated = true;
                               t = new Thread(new PlayAnimation());
                               t.start();
                               bouton.setEnabled(false);
                               bouton2.setEnabled(true);                     
                       }
               }              
        }
        
        class Bouton2Listener  implements ActionListener{
 
               public void actionPerformed(ActionEvent e) {
                       
                                              JOptionPane jop = new JOptionPane();               
                       int option = jop.showConfirmDialog(null, "Voulez-vous arrêter l'animation ?", "Arrêt de l'animation", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                       
                       if(option != JOptionPane.NO_OPTION && option != JOptionPane.CANCEL_OPTION && option != JOptionPane.CLOSED_OPTION)
                       {
                               animated = false;      
                               bouton.setEnabled(true);
                               bouton2.setEnabled(false);
                       }
               }              
        }       
        
        class PlayAnimation implements Runnable{
 
               public void run() {
                       go();                  
               }              
        }
        
        
        class FormeListener implements ActionListener{
 
               public void actionPerformed(ActionEvent e) {
                       pan.setForme(combo.getSelectedItem().toString());
               }              
        }
        
        class MorphListener implements ActionListener{
 
               public void actionPerformed(ActionEvent e) {
                       //Si la case est cochée, activation du mode morphing
                       if(morph.isSelected())pan.setMorph(true);
                       //Sinon rien !
                       else pan.setMorph(false);
               }              
        }       
}


L'une des instructions intéressantes se trouve ici :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
JOptionPane jop = new JOptionPane();                 
int option = jop.showConfirmDialog(null, "Voulez-vous lancer l'animation ?", "Lancement de l'animation", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                       
if(option == JOptionPane.OK_OPTION)
{
        animated = true;
        t = new Thread(new PlayAnimation());
        t.start();
        bouton.setEnabled(false);
        bouton2.setEnabled(true);                     
}


Et l'autre, là :

Code : Java -
1
2
3
4
5
6
7
8
9
JOptionPane jop = new JOptionPane();                 
int option = jop.showConfirmDialog(null, "Voulez-vous arrêter l'animation ?", "Arrêt de l'animation", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
 
if(option != JOptionPane.NO_OPTION && option != JOptionPane.CANCEL_OPTION && option != JOptionPane.CLOSED_OPTION)
{
        animated = false;      
        bouton.setEnabled(true);
        bouton2.setEnabled(false);
}


Voyons ce qu'il se passe ici :
  • nous initialisons notre objet JOptionPane : rien d'étonnant ;
  • par contre, au lieu d'afficher la boîte, nous affectons le résultat que renvoie la méthode showConfirmDialog() dans une variable de type int ;
  • nous nous servons de cette variable afin de savoir quel bouton a été cliqué (oui ou non).


En fait, lorsque vous cliquez sur l'un des deux boutons présents sur cette boîte, vous pouvez affecter ici deux valeurs de type int :
  • la valeur correspondant à l'entier JOptionPane.OK_OPTION vaut 0 (JOptionPane.YES_OPTION à la même valeur) ;
  • la valeur correspondant à l'entier JOptionPane.NO_OPTION vaut 1 ;
  • la valeur correspondant à l'entier JOptionPane.CANCEL_OPTION pour la boîte apparaissant lors du clic sur "Stop" vaut 2 ;
  • la valeur correspondant à l'entier JOptionPane.CLOSED_OPTION pour la même boîte que ci-dessus, vaut -1.


En comparant la valeur de notre entier avec l'une des deux options, nous pouvons en déduire quel bouton a été cliqué et donc agir en conséquence !

Voici deux screenshots du résultat obtenu :


Vous commencez à maîtriser les JOptionPane, on dirait...
Si on continuait ?...

Les boîtes de saisie

Je suis sûr que vous avez deviné ce à quoi ces boîtes peuvent servir...
Oui, tout à fait, nous allons pouvoir faire des saisies dans ces boîtes ! Et même encore mieux... Nous pourrons même avoir une boîte de dialogue qui propose des choix dans une liste déroulante.

Je sens que vous êtes pressés de commencer. Alors allons-y.
Vous savez déjà que nous allons utiliser l'objet JOptionPane, et les plus curieux d'entre vous ont sûrement dû jeter un oeil aux autres méthodes proposés par cet objet...

Ici, nous allons utiliser la méthode showInputDialog(Component parent, String message, String title, int messageType) .

Voici un code mettant en oeuvre cette méthode :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import javax.swing.JOptionPane;
 
public class Test {
 
        public static void main(String[] args) {
               JOptionPane jop = new JOptionPane(), jop2 = new JOptionPane();
               String nom = jop.showInputDialog(null, "Veuillez décliner votre identité !", "Gendarmerie nationale !", JOptionPane.QUESTION_MESSAGE);
               jop2.showMessageDialog(null, "Votre nom est " + nom, "Identité", JOptionPane.INFORMATION_MESSAGE);
        }
}

Vous pouvez constater que cette méthode retourne une chaîne de caractères !


Voici le résultat :


Rien d'extraordinaire...

Maintenant, voyons comment on incorpore une liste dans une boîte de ce genre... Vous allez voir, c'est simplissime !


Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import javax.swing.JOptionPane;
 
public class Test {
 
        public static void main(String[] args) {
               String[] sexe = {"masculin", "féminin", "indéterminé"};
               JOptionPane jop = new JOptionPane(), jop2 = new JOptionPane();
               String nom = (String)jop.showInputDialog(null, 
                                                                            "Veuillez décliner votre sexe !",
                                                                            "Gendarmerie nationale !",
                                                                             JOptionPane.QUESTION_MESSAGE,
                                                                            null,
                                                                            sexe,
                                                                            sexe[2]);
               jop2.showMessageDialog(null, "Votre sexe est " + nom, "Etat civil", JOptionPane.INFORMATION_MESSAGE);
        }
}


Ce code nous donne :

Nous avons utilisé la méthode avec des paramètres en plus, les voici :
  • les quatre premiers, vous connaissez maintenant ;
  • le deuxième null correspond à l'icône que vous souhaitez passer ;
  • ensuite, vous devez passer un tableau de String afin de remplir la combo dans la boîte ;
  • le dernier paramètre correspond à la valeur à  par défaut.

Cette méthode retourne aussi un objet, mais de type Object, comme si vous récupériez la valeur directement dans la combo !
Donc pensez à faire un cast.


Voici maintenant une variante de ce que vous venez de voir : nous allons utiliser ici la méthode showOptionDialog() .
Celle-ci fonctionne à peu près comme la méthode précédente sauf qu'elle prend un paramètre de plus et que le type de retour n'est pas un objet, mais un entier !

Ce type de boîte propose, au lieu d'une combo, un choix de boutons correspondant aux éléments passés en paramètres (tableau de String) ; elle prend aussi une valeur par défaut mais retourne l'indice de l'élément dans la liste, et non l'élément lui-même.

Je pense que vous vous y connaissez assez pour comprendre le code suivant :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import javax.swing.JOptionPane;
 
public class Test {
 
        public static void main(String[] args) {
               String[] sexe = {"masculin", "féminin", "indéterminé"};
               JOptionPane jop = new JOptionPane(), jop2 = new JOptionPane();
               int rang = jop.showOptionDialog(null, 
                                                                            "Veuillez décliner votre sexe !",
                                                                            "Gendarmerie nationale !",
                                                                             JOptionPane.YES_NO_CANCEL_OPTION,
                                                                             JOptionPane.QUESTION_MESSAGE,
                                                                            null,
                                                                             sexe,
                                                                            sexe[2]);
               jop2.showMessageDialog(null, "Votre sexe est " + sexe[rang], "Etat civil", JOptionPane.INFORMATION_MESSAGE);
        }
}


Ce qui nous donne :


Voilà, vous en avez terminé avec les boîtes de saisie...
Cependant, vous devez vous demander si vous ne pouvez pas ajouter des composants sur ces boîtes.
C'est vrai, vous pourriez avoir besoin de plus de renseignements, on ne sait jamais... Je vous propose donc de vous montrer comment créer vos propres boîtes de dialogue !

En avant, mes ZérOs ! Hissez haut !

Des boîtes de dialogue personnalisées

Je me doute bien que vous devez être impatients de faire vos propres boîtes de dialogue...
Il est vrai que dans certains cas, vous en aurez besoin, donc allons-y gaiement !

Je vais maintenant vous révéler un secret bien gardé : les boîtes de dialogue héritent de la classe JDialog.
Vous avez donc deviné que nous allons créer une classe dérivée de cette dernière.

Commençons par faire un nouveau projet.
Créez une nouvelle classe dans Eclipse, appelons-la ZDialog héritée de la classe citée ci-dessus, et mettez-y le code suivant :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import javax.swing.JDialog;
import javax.swing.JFrame;
 
 
public class ZDialog extends JDialog {
 
        public ZDialog(JFrame parent, String title, boolean modal){
               //On appelle le construteur de JDialog correspondant
               super(parent, title, modal);
               //On spécifie une taille
               this.setSize(200, 80);
               //La position
               this.setLocationRelativeTo(null);
               //La boîte ne devra pas être redimensionnable
               this.setResizable(false);
               //Enfin on l'affiche
               this.setVisible(true);
               //Tout ceci ressemble à ce que nous faisons depuis le début avec notre JFrame...
        }
}


Maintenant, faisons une classe qui va tester notre ZDialog :

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
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;
 
 
public class Fenetre extends JFrame {
 
        private JButton bouton = new JButton("Appel à la ZDialog");
        
        public Fenetre(){
               
               this.setTitle("Ma JFrame");
               this.setSize(300, 100);
               this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               this.setLocationRelativeTo(null);
               
               this.getContentPane().setLayout(new FlowLayout());
               this.getContentPane().add(bouton);
               bouton.addActionListener(new ActionListener(){
 
                       public void actionPerformed(ActionEvent arg0) {
                               ZDialog zd = new ZDialog(null, "Coucou les ZérOs", true);
                       }
                       
               });
               
               this.setVisible(true);
               
        }
        
        public static void main(String[] main){
               Fenetre fen = new Fenetre();
        }
        
}


Voilà le résultat ; bon, c'est un début :


Je pense que vous avez deviné à quoi servaient les paramètres du constructeur... Mais nous allons tout de même les expliciter :
  • JFrame Parent correspond à l'objet parent ;
  • String title correspond au titre de notre boîte ;
  • boolean modal correspond à la modalité. true : boîte modale, false : boîte non modale.


Rien de compliqué... Il est donc temps de mettre des composants sur notre objet...
Par contre, vous conviendrez que lorsque nous faisons un tel composant, nous voulons quelque chose de plus qu'une réponse à une question ouverte (oui / non), une chaîne de caractères ou encore un choix dans une liste... Nous en voulons encore plus ! Plusieurs saisies, avec plusieurs listes : en même temps !

Mais vous avez vu que nous devrons récupérer les informations choisies dans certains cas, mais pas tous : nous allons donc devoir déterminer les différents cas ainsi que les choses à faire.

Nous partons du fait que notre boîte aura un bouton "OK" et "Annuler" : dans le cas où l'utilisateur clique sur "OK", on récupérera les informations, et si l'utilisateur clique sur "Annuler", non.
Tout ceci en tenant compte de la modalité de notre boîte...
D'ailleurs, comment va-t-on faire pour dire à notre boîte de mettre fin au dialogue ?

Tout simplement en utilisant la méthode setVisible(false);, cette instruction met fin au dialogue !
Ceci signifie aussi que le dialogue commence au moment où l'instruction setVisible(true); est exécutée. De ce fait, nous allons sortir cette instruction du constructeur de notre objet et nous allons la mettre dans une méthode à part.

Code : Java -
1
2
3
4
5
6
7
8
9
//Cas où notre ZDialog renverra le contenu
//D'un JTextField nommé jtf
public String showZDialog(){
    this.setVisible(true);
    //Le dialogue prend fin
    //SI on a cliqué sur OK, on envoie, sinon on envoie chaîne vide !
    return jtf.getText();
 
}


Il nous reste un dernier point à gérer...
Comment récupérer les informations saisies dans notre boîte depuis notre fenêtre, vu que nous voulons plusieurs informations ?

C'est vrai qu'on ne peut retourner qu'une valeur à la fois...
Mais il peut y avoir plusieurs réponses à cette question.
  • Dans le cas où nous n'avons qu'un composant, nous pouvons adapter la méthode showZDialog() au type de retour du composant utilisé.
  • Dans notre cas, nous voulons plusieurs composants, donc plusieurs valeurs, vous pouvez :
    • retourner une collection de valeurs (ArrayList...) ;
    • faire des accesseurs dans votre ZDialog ;
    • créer un objet dont le rôle est de collecter les informations de votre boîte et de retourner cet objet...
    • ...



Nous allons opter pour un objet qui collectera les informations et nous retournerons cet objet à la fin de la méthode showZDialog().
Avant de nous lancer dans la création de cet objet, nous devons savoir ce que nous allons mettre dans notre boîte...

Nous allons faire une boîte permettant de spécifier les caractéristiques d'un personnage de jeu vidéo :
  • son nom : un champ de saisie ;
  • son sexe : une combo ;
  • sa taille : un champ de saisie ;
  • sa couleur de cheveux : une combo ;
  • sa tranche d'âge : des radios.

Pour le placement des composants, l'objet JDialog est exactement identique à un objet JFrame (BorderLayout par défaut, ajout de composant au conteneur...).


Nous pouvons donc faire notre objet contenant les informations de notre boîte de dialogue, je l'ai appelé ZDialogInfo :

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
public class ZDialogInfo {
 
        private String nom, sexe, age, cheveux, taille;
 
        public ZDialogInfo(){}
        public ZDialogInfo(String nom, String sexe, String age,
                                              String cheveux, String taille){
               this.nom = nom;
               this.sexe = sexe;
               this.age = age;
               this.cheveux = cheveux;
               this.taille = taille;
        }
        
        //------------------------------------
        
        public String getNom() {
               return nom;
        }
 
        public void setNom(String nom) {
               this.nom = nom;
        }
 
        //------------------------------------
        
        public String getSexe() {
               return sexe;
        }
 
        public void setSexe(String sexe) {
               this.sexe = sexe;
        }
        
        //------------------------------------
 
        public String getAge() {
               return age;
        }
 
        public void setAge(String age) {
               this.age = age;
        }
 
        //------------------------------------
        public String getCheveux() {
               return cheveux;
        }
 
        public void setCheveux(String cheveux) {
               this.cheveux = cheveux;
        }
 
        //------------------------------------
        public String getTaille() {
               return taille;
        }
 
        public void setTaille(String taille) {
               this.taille = taille;
        }
        
        //-------------------------------------
        
        public String toString(){
               String str;
               if(this.nom != null && this.sexe != null &&
                               this.taille != null && this.age != null &&
                               this.cheveux != null){
                       str = "Description de l'objet InfoZDialog";
                       str += "Nom : " + this.nom + "\n";
                       str += "Sexe : " + this.sexe + "\n";
                       str += "Age : " + this.age + "\n";
                       str += "Cheveux : " + this.cheveux + "\n";
                       str += "Taille : " + this.taille + "\n";
               }
               else{
                       str = "Aucune information !";
               }
               return str;
        }
}


L'avantage avec cette méthode, c'est que nous n'avons pas à nous soucier de savoir si nous avons annulé la saisie ou non : l'objet d'information renverra toujours quelque chose...

Voici le code source de notre boîte perso :

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
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.ButtonGroup;
import javax.swing.JTextField;
 
 
public class ZDialog extends JDialog {
 
        private ZDialogInfo zInfo = new ZDialogInfo();
        private JLabel nomLabel, sexeLabel, cheveuxLabel, ageLabel, tailleLabel, taille2Label, icon;
        private JRadioButton tranche1, tranche2, tranche3, tranche4;
        private JComboBox sexe, cheveux;
        private JTextField nom, taille;
        
        /**
         * Constructeur
         * @param parent
         * @param title
         * @param modal
         */
        public ZDialog(JFrame parent, String title, boolean modal){
               super(parent, title, modal);
               this.setSize(550, 270);
               this.setLocationRelativeTo(null);
               this.setResizable(false);
               this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
               this.initComponent();
        }
        
        /**
         * Méthode appelée pour utiliser la boîte 
         * @return zInfo
         */
        public ZDialogInfo showZDialog(){
               this.setVisible(true);         
               return this.zInfo;             
        }
        
        /**
         * Initialise le contenu de la boîte
         */
        private void initComponent(){
               //Icone
               icon = new JLabel(new ImageIcon("images/icone.jpg"));
               JPanel panIcon = new JPanel();
               panIcon.setBackground(Color.white);
               panIcon.setLayout(new BorderLayout());
               panIcon.add(icon);
               
               //Le nom
               JPanel panNom = new JPanel();
               panNom.setBackground(Color.white);
               panNom.setPreferredSize(new Dimension(220, 60));
               nom = new JTextField();
               nom.setPreferredSize(new Dimension(100, 25));
               panNom.setBorder(BorderFactory.createTitledBorder("Nom du personnage"));
               nomLabel = new JLabel("Saisir un nom :");
               panNom.add(nomLabel);
               panNom.add(nom);
               
               //Le sexe
               JPanel panSexe = new JPanel();
               panSexe.setBackground(Color.white);
               panSexe.setPreferredSize(new Dimension(220, 60));
               panSexe.setBorder(BorderFactory.createTitledBorder("Sexe du personnage"));
               sexe = new JComboBox();
               sexe.addItem("Masculin");
               sexe.addItem("Féminin");
               sexe.addItem("Indéterminé");
               sexeLabel = new JLabel("Sexe : ");
               panSexe.add(sexeLabel);
               panSexe.add(sexe);
               
               //L'âge 
               JPanel panAge = new JPanel();
               panAge.setBackground(Color.white);
               panAge.setBorder(BorderFactory.createTitledBorder("Age du personnage"));
               panAge.setPreferredSize(new Dimension(440, 60));
               tranche1 = new JRadioButton("15 - 25 ans");
               tranche1.setSelected(true);
               tranche2 = new JRadioButton("26 - 35 ans");
               tranche3 = new JRadioButton("36 - 50 ans");
               tranche4 = new JRadioButton("+ de 50 ans");
               ButtonGroup bg = new ButtonGroup();
               bg.add(tranche1);
               bg.add(tranche2);
               bg.add(tranche3);
               bg.add(tranche4);
               panAge.add(tranche1);
               panAge.add(tranche2);
               panAge.add(tranche3);
               panAge.add(tranche4);
               
               
               //La taille
               JPanel panTaille = new JPanel();
               panTaille.setBackground(Color.white);
               panTaille.setPreferredSize(new Dimension(220, 60));
               panTaille.setBorder(BorderFactory.createTitledBorder("Taille du personnage"));
               tailleLabel = new JLabel("Taille : ");
               taille2Label = new JLabel(" cm");
               taille = new JTextField("180");
               taille.setPreferredSize(new Dimension(90, 25));
               panTaille.add(tailleLabel);
               panTaille.add(taille);
               panTaille.add(taille2Label);
               
               //La couleur des cheveux
               JPanel panCheveux = new JPanel();
               panCheveux.setBackground(Color.white);
               panCheveux.setPreferredSize(new Dimension(220, 60));
               panCheveux.setBorder(BorderFactory.createTitledBorder("Couleur de cheveux du personnage"));
               cheveux = new JComboBox();
               cheveux.addItem("Blond");
               cheveux.addItem("Brun");
               cheveux.addItem("Roux");
               cheveux.addItem("Blanc");
               cheveuxLabel = new JLabel("Cheveux");
               panCheveux.add(cheveuxLabel);
               panCheveux.add(cheveux);
               
               
               JPanel content = new JPanel();
               content.setBackground(Color.white);
               content.add(panNom);
               content.add(panSexe);
               content.add(panAge);
               content.add(panTaille);
               content.add(panCheveux);
               
               JPanel control = new JPanel();
               JButton okBouton = new JButton("OK");
               
               okBouton.addActionListener(new ActionListener(){
                       public void actionPerformed(ActionEvent arg0) {                           
                               zInfo = new ZDialogInfo(nom.getText(), (String)sexe.getSelectedItem(), getAge(), (String)cheveux.getSelectedItem() ,getTaille());
                               setVisible(false);
                       }
                       
                       public String getAge(){
                               return (tranche1.isSelected()) ? tranche1.getText() : (tranche2.isSelected()) ? tranche2.getText() : (tranche3.isSelected()) ? tranche3.getText() : (tranche4.isSelected()) ? tranche4.getText() : tranche1.getText();   
                       }
                       
                       public String getTaille(){
                               return (taille.getText().equals("")) ? "180" : taille.getText();
                       }                      
               });
               
               JButton cancelBouton = new JButton("Annuler");
               cancelBouton.addActionListener(new ActionListener(){
                       public void actionPerformed(ActionEvent arg0) {
                               setVisible(false);
                       }                      
               });
               
               control.add(okBouton);
               control.add(cancelBouton);
               
               this.getContentPane().add(panIcon, BorderLayout.WEST);
               this.getContentPane().add(content, BorderLayout.CENTER);
               this.getContentPane().add(control, BorderLayout.SOUTH);
        }
        
}

J'ai ajouté une image, mais vous n'y êtes nullement obligés !
Vous constaterez aussi que j'ai ajouté une bordure à nos JPanel afin de faire plus... Zoli...


Et le code source permettant de tester cette boîte :

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
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
 
 
public class Fenetre extends JFrame {
 
        private JButton bouton = new JButton("Appel à la ZDialog");
        
        public Fenetre(){
               
               this.setTitle("Ma JFrame");
               this.setSize(300, 100);
               this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               this.setLocationRelativeTo(null);
               
               this.getContentPane().setLayout(new FlowLayout());
               this.getContentPane().add(bouton);
               bouton.addActionListener(new ActionListener(){
 
                       public void actionPerformed(ActionEvent arg0) {
                               ZDialog zd = new ZDialog(null, "Coucou les ZérOs", true);
                               ZDialogInfo zInfo = zd.showZDialog(); 
                               JOptionPane jop = new JOptionPane();
                               jop.showMessageDialog(null, zInfo.toString(), "Informations personnage", JOptionPane.INFORMATION_MESSAGE);
                       }
                       
               });
               
               this.setVisible(true);
               
        }
        
        public static void main(String[] main){
               Fenetre fen = new Fenetre();
        }
        
}

Voici des screenshots obtenus


De la ZDialog

Lorsqu'on valide la saisie



Lorsqu'on annule la saisie




Voilà : nous arrivons à la fin de chapitre, riche en nouveautés...

En route pour le topo habituel et le petit QCM des familles...

Ce qu'il faut retenir

  • Les boîtes de dialogue s'utilisent, sauf boîtes personnalisées, avec l'objet JOptionPane.
  • La méthode showMessageDialog() permet d'afficher un message informatif.
  • La méthode showConfirmDialog() permet d'afficher une boîte attendant une réponse à une question ouverte (oui / non).
  • La méthode citée ci-dessus retourne un entier correspondant au bouton sur lequel vous avez cliqué.
  • La méthode showInputDialog() affiche une boîte attendant une saisie de la part de l'utilisateur ou une sélection dans une liste.
  • Cette méthode retourne soit un String dans le cas d'une saisie, soit un Object dans le cas d'une liste.
  • La méthode showOptionDialog() affiche une boîte attendant le clic sur une option proposée à l'utilisateur.
  • Celle-ci retourne l'indice de l'élément sur lequel vous avez cliqué, ou un indice négatif pour tous les autres cas !
  • Les boîtes de dialogue sont dites modales : aucune interaction hors de la boîte n'est possible tant que celle-ci n'est pas fermée !
  • Pour faire une boîte de dialogue personnalisée, vous devez créer une classe héritée de JDialog.
  • Pour les boîtes personnalisées, le dialogue commence lorsque la méthode setVisible(true) est invoquée et se termine lorsque la méthode setVisible(false) est appelée !

Chapitre très simple, là aussi, mais je tenais à vous féliciter.
Vous avez dû remarquer que vous avez réellement progressé en Java depuis le début de ce tuto, et vous devez vous rendre compte qu'en définitive, faire des IHM en Java n'est pas si compliqué qu'il n'y paraît... Il y a beaucoup de choses à savoir, mais le plus important n'est pas de tout connaître par coeur, mais de savoir retrouver l'information rapidement !

Trêve de compliments, sinon vous ne travaillerez plus...

Je vous propose donc maintenant de continuer par un chapitre qui risque de vous plaire tout autant : Les menus.


0 comments to "LECON 311"

Post a Comment

Powered by Blogger.

About This Blog

Aller au debut de la page