Les boîtes de dialogue

Chapitres traités   

Jusqu'ici, nous avons appris à placer des composants dans une fenêtre. En général, ces composants restent affichés en permanence. Or, pour certaines applications, nous avons besoin d'établir un dialogue temporaire avec l'utilisateur. Nous pourrions certes y parvenir en exploitant les possibilités d'ajout ou de suppression dynamique de composants, ou éventuellement en recourant à la méthode setVisible(false). Mais la boîte de dialogue offre une solution beaucoup plus adaptée.

Elle permet en effet de regrouper n'importe quels composants dans une sorte de fenêtre que nous faisons apparaître ou disparaître globalement. Par ailleurs, l'utilisateur est parfaitement habitué à son ergonomie, dans la mesure où elle est très utilisée dans les logiciels du commerce.

Au travers de cette étude, nous allons apprendre à créer et à exploiter de telles boîtes de dialogue en y introduisant les composants de notre choix. Auparavant, nous présenterons quelques boîtes de dialogue standard fournies par Java et qui pourront nous simplifier la tâche dans certaines situations simples : affichage d'un message, demande de confirmation, choix d'une option dans une liste, saisie d'un texte, sélecteur de fichier et sélecteur de couleur.

Choix du chapitre Principe général d'une boîte de dialogue

 l'image de la plupart des systèmes de fenêtrage, AWT fait la distinction entre les boîtes de dialogue modales et non modales :

  1. Une boîte de dialogue modale ne permet pas à l'utilisateur d'interagir avec d'autres fenêtres de l'application tant quelle demeure ouverte. Vous l'utilisez lorsque vous avez besoin de récupérer des informations de la part de l'utilisateur avant de poursuivre l'exécution du programme. Par exemple, quand l'utilisateur demande à lire un fichier pour que le programme puisse entreprendre une opération de lecture. L'application ne peut continuer à s'exécuter que lorsque l'utilisateur a fermé la boîte de dialogue.
  2. Une boîte de dialogue non modale autorise l'utilisateur à interagir avec les autres fenêtres de l'application alors qu'elle est ouverte. La boîte de dialogue Rechercher/Remplacer en est un exemple. Elle peut rester apparente aussi longtemps que nécessaire pendant que l'utilisateur manipule les différentes fenêtres.
Nous allons commencer l'étude par une boîte de dialogue modale simple contenant éventuellement au choix : un seul message, une zone de saisie, un ensemble d'options ou une confirmation. Swing dispose d'une classe très utile pour cela, JOptionPane, qui vous permet d'afficher une boîte de dialogue standard sans avoir à écrire de code spécifique.

Il existe également deux autres boîtes de dialogues plus sophistiquées :

  1. JFileChooser : qui permet de gérer et de choisir un ou plusieurs fichiers.
  2. JColorChooser : qui permet à un utilisateur de choisir une couleur à partir d'une palette.
Nous verrons ensuite comment créer des boîtes de dialogue plus complexe, à partir de la classe JDialog, en implémentant les notres de façon personnalisées. Nous verrons ainsi comment échanger des données entre une application et une boîte de dialogue.

 

Choix du chapitre Boîtes de dialogue d'options - JOptionPane

Swing propose un ensemble de boîtes de dialogues standard, prêtes à l'emploi, qui permettent de demander à l'utilisateur de fournir une information. Swing a prévu un jeu de dialogues préfabriqués, accessibles à partir de méthodes statiques de la classe JOptionPane. De nombreuses variantes sont possibles ; JOptionPane les classe en quatre groupes de base :

Dialogue de message : showMessageDialog() - Affiche un message et attend que l'utilisateur clique sur OK (validation de lecture du message).


import javax.swing.*;

public class Dialogue {
    public static void main(String[] args) {
       JOptionPane.showMessageDialog(null, "Bienvenue..."); 
    }
}

  

Cette boîte de dialogue contient les composants suivant : une icône, un message et un bouton OK.
§

Dialogue de confirmation : showConfirmDialog() - Affiche un message et attend une confirmation de la part de l'utilisateur. Les boutons de réponse sont généralement Oui, Non et Annuler.


import javax.swing.*;

public class Dialogue {
    public static void main(String[] args) {
       JOptionPane.showConfirmDialog(null, "Voulez-vous continuer ?"); 
    }
}


  

Dialoque de saisie : showInputDialog() - Affiche un message et récupère une valeur saisie par l'utilisateur.


import javax.swing.*;

public class Dialogue {
    public static void main(String[] args) {
       JOptionPane.showInputDialog(null, "Votre nom et prénom :"); 
    }
}


  

La boîte de dialogue de saisie comprend un composant supplémentaire pour recueillir l'entrée de l'utilisateur. Il peut s'agir d'un champ de texte dans lequel il tape une chaîne quelconque, ou d'une zone de liste déroulante dans laquelle il sélectionne une valeur.

Dialogue d'option : showOptionDialog() - Le type le plus général, vous lui passez vos propres composants, qui se retrouvent affichés dans le dialogue, comme des boîtes combo, un ensemble de boutons, un ensemble d'objets hétérogènes.


import javax.swing.*;

public class Dialogue {
  public static void main(String[] args) {
    JTextField utilisateur = new JTextField();
    JPasswordField passe = new JPasswordField();
    JOptionPane.showOptionDialog(null, 
      new Object[] {"Votre nom :", utilisateur, "Mot de passe :", passe},
      "Connexion",
      JOptionPane.OK_CANCEL_OPTION,
      JOptionPane.QUESTION_MESSAGE, null, null, null); 
  }
}
  

Avec la méthode showOptionDialog(), vous pouvez spécifier un ensemble arbitraire d'options en fournissant un tableau d'objets. Chaque élément du tableau est traité de la façon suivante :

  1. String : Un bouton est créé avec la chaîne comme libellé.
  2. Icon : Un bouton est créé avec l'icône comme libellé.
  3. Component : Le composant est affiché.
  4. tout autre objet : La méthode toString() est appliquée et un bouton est créé avec pour libellé la chaîne résultante.

Les dialogues affichés par JOptionPane sont modaux, ce qui signifie, nous l'avons déjà vu, qu'ils bloquent les autres entrées de l'application lorsqu'ils sont affichés.

Les différents types d'icône

L'icône placée à gauche dans la boîte de dialogue standard dépend du type de message. Il en existe cinq :

Le type PLAIN_MESSAGE ne possède pas d'icône. Pour chaque type de boîte de dialogue, il existe la méthode setIcon() vous permettant de fournir votre propre icône.

Choisir son type de message

Vous pouvez spécifier un message pour chaque type de boîte de dialogue. Ce message peut être une chaîne, une icône, un composant d'interface utilisateur ou tout autre objet. Voici comment est affiché l'objet message suivant son type :

  1. String : La chaîne est affichée.
  2. Icon : L'icône est affichée.
  3. JComponent : Le composant est affiché.
  4. Object[] : Tous les objets du tableau sont affichés les uns au-dessus des autres.
  5. tout autre objet : La méthode toString() est appliquée et la chaîne résultante est affichée.

Bien sûr, le message le plus fréquent est celui de type chaîne. Un objet Component offre une souplesse optimale puisque vous pouvez redéfinir la méthode paintComponent() pour dessiner tout ce que vous souhaitez.

Astuce : Une chaîne de message peut contenir des caractères de fin de ligne ('\n'). L'affichage est alors réparti sur plusieurs lignes.
§

Les différents types de bouton

Les boutons situés en bas de la boîte de dialogue dépendent de son type et du type d'option. Les méthodes showMessageDialog() et showInputDialog() implémentent uniquement un jeu standard de boutons (respectivement OK et OK/Cancel).

La méthode showConfirmMessage() vous permet de choisir parmi les quatres options suivantes :

Valeurs renvoyées par les méthode statiques

Les méthodes showConfirmDialog() et showOptionDialog() renvoient des entiers pour indiquer le bouton que l'utilisateur a sélectionné. Pour une boîte de dialogue d'options, il s'agit de l'indice de l'élément choisi ou de la valeur CLOSED_OPTION si l'utilisateur a fermé la boîte de dialogue au lieu de faire une sélection. Pour une boîte de dialogue de confirmation, la valeur renvoyée peut être l'une des suivantes :

Création d'une instance de boîte de dialogue

Au lieu d'utiliser l'une des méthodes statiques pour afficher un dialogue JOptionPane, nous pouvons aussi créer directement un objet (de type JOptionPane) avec les propriétés désirées. Ces réglages sont ainsi conservés dans le temps. Une fois que vous avez créé votre objet en choisissant le constructeur le plus adapté, vous devez faire appel ensuite à la méthode createDialog() qui fabriquera réellement votre boîte de dialogue en fonction des propriétés que vous avez choisies de mettre en place.

Voici la liste des constructeurs qui sont à votre disposition :

  1. JOptionPane() : Création d'une boîte d'option avec un message de test "JOptionPane message" avec un bouton OK et sans icône. Boîte de dialogue de type message.
  2. JOptionPane(Object message) : Par rapport au précédent, vous choisissez votre message. Boîte de dialogue de type message.
  3. JOptionPane(Object message, int typeMessage) : Cette fois-ci vous précisez en plus le type de message (icône correspondante). Boîte de dialogue de type message.
  4. JOptionPane(Object message, int typeMessage, int typeOption) : Par rapport au précédent, vous choisissez en plus les boutons qui feront parti de votre boîte de dialogue. Boîte de dialogue de type confirmation.
  5. JOptionPane(Object message, int typeMessage, int typeOption, Icon icône) : Par rapport au précédent, vous choisissez en plus votre icône personnalisée. Boîte de dialogue de type confirmation.
  6. JOptionPane(Object message, int typeMessage, int typeOption, Icon icône, Object[] options) : Par rapport au précédent, vous placez en plus l'ensemble des objets qui feront parti de votre boîte de dialogue. Boîte de dialogue de type saisie ou option.
  7. JOptionPane(Object message, int typeMessage, int typeOption, Icon icône, Object[] options, Object valeurInitiale) : Exactement le même que le précédent, mais vous choisissez votre composant qui sera visualisé par défaut (utile pour les boîtes combo). Boîte de dialogue de type saisie ou option.
Exemple de codage

import javax.swing.*;

public class Dialogue {
   public static void main(String[] args) {
      JOptionPane dialogue = new JOptionPane("Bonjour à tous", JOptionPane.INFORMATION_MESSAGE);
      JDialog boîte = dialogue.createDialog("Bienvenue");
      boîte.setVisible(true);
   }
}

Il existe une deuxième méthode createDialog() qui possède deux paramètres et qui prend en premier argument la fenêtre parente afin de bien mettre en oeuvre une boîte de dialogue modale.

Cette façon de faire reste exceptionnelle puisque vous devez systématiquement passer par trois phases :
  1. Vous devez précisez pas mal d'informations au constructeur durant la phase de création.
  2. Vous devez créer la boîte de dialogue de type JDialog au travers de la méthode createDialog().
  3. Il faut ensuite afficher cette boîte de dialogue au travers de la méthode setVisible(true) de JDialog.

Pour toutes ces raisons, il généralement souhaitable d'utiliser plutôt les méthodes statiques de JOptionPane et de choisir la plus adaptée à la situation requise.

Comment choisir sa boîte de dialogue standard JOptionPane

La diversité des choix peut sembler déconcertant, mais en pratique c'est très simple :

  1. Choisissez le type de boîte de dialogue (message, confirmation, options ou entrée).
  2. Choisissez l'icône (erreur, information, avertissement, question, aucune ou personnalisée).
  3. Choisissez le message (chaîne, icône, composant personnalisé ou un tableau d'objets).
  4. Pour une boîte de dialogue de confirmation, choisissez un type d'option pour le jeu de boutons (default, Oui/Non, Oui/Non/Annuler ou OK/Annuler).
  5. Pour une boîte de dialogue d'options, choisissez les options (chaîne, icône, composant personnalisé), et l'option par défaut.
  6. Pour une boîte de dialogue de saisie, choisissez entre un champ de texte et une zone de liste déroulante.
  7. Déterminez la méthode appropriée à appeler dans la classe JOptionPane.

Dans les chapitres qui suivent, nous allons reprendre chacune de ces boîtes de dialogue, afin d'exploiter au maximun les possibilités qui nous sont offertes.
§

 

Choix du chapitre Les boîtes de message

Java dispose de méthodes standard vous permettant de fournir à l'utilisateur un message qui reste affiché tant qu'il n'agit pas sur un bouton OK. Plus précisément, la classe JOptionPane dispose de la méthode statique showMessageDialog(), vue plus haut, permettant d'afficher et de gérer automatiquement une telle boîte. Cette méthode dispose de plusieurs variantes dont la liste est fournie ci-dessous.

  1. static void showMessageDialog(Component composantParent, Object message) : Affiche automatiquement une boîte de dialogue de type message, dont le titre est intitulé "Message", avec une icône de type information et avec un bouton OK. Vous spécifiez éventuellement en argument la fenêtre parente et surtout le contenu de votre message (qui peut être de nature différente).
  2. static void showMessageDialog(Component composantParent, Object message, String titre, int typeMessage) : Même boîte de message que précédemment, mais cette fois-ci, vous pouvez choisir votre titre et votre icône.
  3. static void showMessageDialog(Component composantParent, Object message, String titre, int typeMessage, Icon icône) : Par rapport à la précédente, vous pouvez placer en plus une icône personnalisée.
Nous pouvons créer un message simple de dialogue avec l'une de ces méthodes showMessageDialog(). Ces méthodes affichent une boîte de dialogue qui contient le message désiré, une icône et un bouton OK qui ferme le dialogue. Le dialogue est modal, ce qui signifie qu'il bloque, en ne revenant que quand l'utilisateur a terminé de consulter le message.

Remarquez au passage que cette méthode statique ne renvoie aucune valeur, ce qui est normal puisqu'il s'agit juste de proposer un message d'information correspondant à la situation actuelle de l'application.

  1. L'argument composantParent spécifie le composant servant de parent au dialogue (c'est le composant qui sera rendu actif quand le dialogue sera terminé, généralement la fenêtre de l'application).
  2. L'argument titre spécifie une chaîne apparaissant dans la barre de tittre du dialogue.
  3. L'argument message est plus complexe. Il est en effet déclaré comme un Object. Nous lui passons généralement une valeur de type String, qui est automatiquement affichée dans un JLabel. Nous pouvons cependant spécifier aussi une icône type Icon qui est également affichée par le JLabel, ou un composant graphique quelconque de JComponent, qui est affiché tel quel. De plus, au lieu de donner un seul objet message, nous pouvons spécifier un tableau d'objets contenant n'importe quelle combinaison de chaînes, d'icônes et de composants.
  4. L'argument typeMessage doit être choisi parmi les constantes WARNING_MESSAGE , QUESTION_MESSAGE , INFO_MESSAGE , ERROR_MESSAGE ou PLAIN_MESSAGE (aucune icône). Ces constantes spécifient le type de message de base à afficher. En général, la personnalisation se limite à l'affichage d'une icône parmi un ensemble standard.
  5. Pour surcharger l'icône par défaut du dialogue, nous pouvons également spécifier une icône personnalisée au paramètre icône.

Dans la suite de ce chapitre, nous allons prendre pleins d'exemples, de la boîte de dialogue la plus rudimentaire (souvent suffisante) à la plus sophistiquée, afin de bien montrer tous les réglages et toutes les configurations qu'il est possible de faire sur une simple boîte de dialogue de message. Bien entendu, nous pourrons faire ses mêmes réglages sur les autres types de boîte de dialogue.

Boîte de message basique activée à partir de la fenêtre principale de l'application

Venons-en tout de suite à notre premier exemple. Une fenêtre principale d'application possède un bouton qui permet d'activer une boîte de dialogue qui nous renseigne sur l'heure qu'il est. Nous utilisons pour cela la boîte de message la plus rudimentaire :


import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.Date;
import javax.swing.*;

public class Dialogue extends JFrame implements ActionListener {
   private JButton heure = new JButton("Quel heure est-il ?");
   
   public Dialogue() {
      super("Dialogue...");
      add(heure, BorderLayout.SOUTH);
      heure.addActionListener(this);
      getContentPane().setBackground(Color.ORANGE);
      setSize(300, 200);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setVisible(true);
   }
   
   public static void main(String[] args) { new Dialogue();  }

   public void actionPerformed(ActionEvent e) {
      SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
      JOptionPane.showMessageDialog(this, heure.format(new Date()));
   }
}

On notera que le premier argument de la méthode showMessageDialog() représente ce que nous nommons - la fenêtre parent (ou propriétaire) - de la boîte de message ; c'est-à-dire celle dans laquelle elle va s'afficher. Remarquez d'ailleurs que la boîte de dialogue ce centre automatiquement par rapport à la fenêtre propriétaire.

Même boîte de dialogue mais en mode console

Il est cependant possible d'afficher une boîte de dialogue indépendamment de toute fenêtre, en donnant à ce premier paramètre la valeur null :


import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JOptionPane;

public class Dialogue  {   
   public static void main(String[] args) { 
      SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
      JOptionPane.showMessageDialog(null, heure.format(new Date()));   
   }
}

Proposer un titre au dialogue et choisir son icône

La boîte de message usuelle ne permet de définir que le contenu du message. Son titre (Message) et l'icône qu'elle renferme - : lettre i comme "information" - sont imposés. Il existe une autre variante de la méthode showMessageDialog() qui permet de choisir :

  1. le contenu du message,
  2. le titre de la boîte,
  3. le type d'icône.

import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JOptionPane;

public class Dialogue  {   
   public static void main(String[] args) { 
      SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
      JOptionPane.showMessageDialog(null, 
        heure.format(new Date()), 
        "Heure actuelle",
        JOptionPane.WARNING_MESSAGE);   
   }
}

Icône personnalisée

Il existe une troisième variante qui, outre les paramètres précédents, permet de choisir une icône quelconque (objet de la classe Icon) qui remplace l'une des icônes standard.

A ce sujet, il est préférable de stipuler la constante JOptionPane.PLAIN_MESSAGE pour bien indiquer que nous choisissons une icône personnalisée. Ceci dit, vous avez la possibilité de proposer un autre choix, cela fonctionnera exactement de la même manière.


import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;

public class Dialogue  {   
   public static void main(String[] args) { 
      SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
      JOptionPane.showMessageDialog(null, 
        heure.format(new Date()), 
        "Heure actuelle",
        JOptionPane.PLAIN_MESSAGE,
        new ImageIcon("montre.gif"));   
   }
}

Choisir son type de message

Jusqu'à présent, le type de message que j'utilise est tout simplement une chaîne de caractères (de type String). Je rappelle que ce message peut être une chaîne, une icône, un composant d'interface utilisateur ou tout autre objet. Voici d'ailleurs comment est affiché l'objet message suivant son type :

  1. String : La chaîne est affichée.
  2. Icon : L'icône est affichée.
  3. JComponent : Le composant est affiché.
  4. Object[] : Tous les objets du tableau sont affichés les uns au-dessus des autres.
  5. tout autre objet : La méthode toString() est appliquée et la chaîne résultante est affichée.

Bien sûr, le message le plus fréquent est celui de type chaîne. Un objet Component offre une souplesse optimale puisque vous pouvez redéfinir la méthode paintComponent() pour dessiner tout ce que vous souhaitez.

Astuce : Une chaîne de message peut contenir des caractères de fin de ligne ('\n'). L'affichage est alors réparti sur plusieurs lignes.
§

Utiliser un JLabel comme type de message pour concerver l'icône d'information

import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;

public class Dialogue  {   
  public static void main(String[] args) { 
    SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
    JLabel message = new JLabel(heure.format(new Date()), new ImageIcon("montre.gif"), JLabel.RIGHT);
    message.setFont(new Font("Arial", Font.BOLD+Font.ITALIC, 24));
    message.setForeground(Color.RED);
    message.setHorizontalTextPosition(JLabel.LEFT);
    JOptionPane.showMessageDialog(null, message, "Heure actuelle", JOptionPane.INFORMATION_MESSAGE);   
  }
}
Utiliser un tableau de chaîne pour proposer à la fois la date et l'heure sur deux lignes

import java.text.*;
import java.util.Date;
import javax.swing.*;

public class Dialogue  {   
  public static void main(String[] args) { 
    DateFormat date = DateFormat.getDateInstance(DateFormat.FULL);
    SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
    String[] message = {date.format(new Date()), heure.format(new Date())};
    JOptionPane.showMessageDialog(null, 
       message, 
       "Aujourd'hui", 
       JOptionPane.PLAIN_MESSAGE,
       new ImageIcon("montre.gif"));   
   }
}

Il est possible de prévoir un tableau de JLabel en lieu et place de ce tableau de chaîne afin de permettre le formatage personnalisé du texte.
§

Prévoir une liste déroulante afin de permettre la visualisation de plusieurs paramètres

import java.text.*;
import java.util.Date;
import javax.swing.*;

public class Dialogue  {   
   public static void main(String[] args) { 
      DateFormat date = DateFormat.getDateInstance(DateFormat.FULL);
      SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
      String[] message = {date.format(new Date()), heure.format(new Date())};
      JOptionPane.showMessageDialog(null, 
        new JComboBox(message), 
        "Aujourd'hui", 
        JOptionPane.PLAIN_MESSAGE,
        new ImageIcon("montre.gif"));   
   }
}
Fabrication d'un nouveau composant qui visualise une horloge en temps réel

import java.awt.*;
import java.awt.event.*;
import java.util.Calendar;
import javax.swing.*;

public class Dialogue  {   
  public static void main(String[] args) { 
    Horloge horloge = new Horloge();
    JOptionPane.showMessageDialog(null, horloge, "Horloge", JOptionPane.INFORMATION_MESSAGE);   
    horloge.arrêt();
  }
}

class Horloge extends JComponent implements ActionListener {
  private Timer timer = new Timer(100, this);
  private double heure; 
  private double minute, seconde;
   
  public Horloge() {
    setPreferredSize(new Dimension(240, 190));
    timer.start();
  }
   
  public void arrêt() {
    timer.stop();
  }
   
  @Override
  protected void paintComponent(Graphics g) {
    Graphics2D dessin = (Graphics2D) g;
    dessin.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    dessin.setStroke(new BasicStroke(5));      
    dessin.drawOval(5, 5, 181, 181);
    dessin.setStroke(new BasicStroke(2));
    dessin.drawLine(96, 5, 96, 183);
    dessin.drawLine(5, 96, 183, 96);
    dessin.setStroke(new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    dessin.setPaint(new Color(0.0F, 0.0F, 1.0F, 0.5F));
    dessin.drawLine(96, 96,
        (int) (96 + 50*Math.cos((heure-3) * 2.0 * Math.PI / 12)), 
        (int) (96 + 50*Math.sin((heure-3) * 2.0 * Math.PI / 12)));
    dessin.drawLine(96, 96,
        (int) (96 + 70*Math.cos((minute-15) * 2.0 * Math.PI / 60)), 
        (int) (96 + 70*Math.sin((minute-15) * 2.0 * Math.PI / 60)));
    dessin.setPaint(new Color(1.0F, 0.0F, 0.0F, 0.5F));
    dessin.drawLine(96, 96,
        (int) (96 + 80*Math.cos((seconde-15) * 2.0 * Math.PI / 60)), 
        (int) (96 + 80*Math.sin((seconde-15) * 2.0 * Math.PI / 60)));
  }

  public void actionPerformed(ActionEvent e) {
    Calendar horaire = Calendar.getInstance();      
    minute = horaire.get(Calendar.MINUTE);
    seconde = horaire.get(Calendar.SECOND);
    heure = horaire.get(Calendar.HOUR)+minute/60;
    repaint();
  }
}

Nous voyons ici toute la puissance des boîtes de dialogue standard. Rien empêche donc de créer le composant qui vous plait et de le placer ensuite dans votre boîte de dialogue, qui constitue ainsi votre message principal. Ici, nous voyons notre horloge qui fonctionne en temps réel avec l'aiguille des secondes qui se déplace automatiquement.

Prévoir un JLabel qui spécifie la date du jour en même temps que l'horloge temps réel que nous venons de mettre en oeuvre

import java.awt.*;
import java.awt.event.*;
import java.text.DateFormat;
import java.util.Calendar;
import javax.swing.*;

public class Dialogue  {   
  public static void main(String[] args) { 
    DateFormat aujourdhui = DateFormat.getDateInstance(DateFormat.FULL);
    Horloge horloge = new Horloge();
    JLabel date = new JLabel(aujourdhui.format(System.currentTimeMillis()));
    date.setFont(new Font("ARIAL", Font.BOLD+Font.ITALIC, 20));
    Object[] date_heure = {date, horloge};
    JOptionPane.showMessageDialog(null, date_heure, "Horloge", JOptionPane.INFORMATION_MESSAGE);   
    horloge.arrêt();
  }
}

class Horloge extends JComponent implements ActionListener {
  private Timer timer = new Timer(100, this);
  private double heure; 
  private double minute, seconde;
   
  public Horloge() {
    setPreferredSize(new Dimension(240, 190));
    timer.start();
  }
   
  public void arrêt() {
    timer.stop();
  }
   
  @Override
  protected void paintComponent(Graphics g) {
    Graphics2D dessin = (Graphics2D) g;
    dessin.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    dessin.setStroke(new BasicStroke(5));      
    dessin.drawOval(5, 5, 181, 181);
    dessin.setStroke(new BasicStroke(2));
    dessin.drawLine(96, 5, 96, 183);
    dessin.drawLine(5, 96, 183, 96);
    dessin.setStroke(new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    dessin.setPaint(new Color(0.0F, 0.0F, 1.0F, 0.5F));
    dessin.drawLine(96, 96,
        (int) (96 + 50*Math.cos((heure-3) * 2.0 * Math.PI / 12)), 
        (int) (96 + 50*Math.sin((heure-3) * 2.0 * Math.PI / 12)));
    dessin.drawLine(96, 96,
        (int) (96 + 70*Math.cos((minute-15) * 2.0 * Math.PI / 60)), 
        (int) (96 + 70*Math.sin((minute-15) * 2.0 * Math.PI / 60)));
    dessin.setPaint(new Color(1.0F, 0.0F, 0.0F, 0.5F));
    dessin.drawLine(96, 96,
        (int) (96 + 80*Math.cos((seconde-15) * 2.0 * Math.PI / 60)), 
        (int) (96 + 80*Math.sin((seconde-15) * 2.0 * Math.PI / 60)));
  }

  public void actionPerformed(ActionEvent e) {
    Calendar horaire = Calendar.getInstance();      
    minute = horaire.get(Calendar.MINUTE);
    seconde = horaire.get(Calendar.SECOND);
    heure = horaire.get(Calendar.HOUR)+minute/60;
    repaint();
  }
}

Là encore, nous pouvons décider d'avoir une boîte de message extrêment riche. Grâce aux tableaux d'objets (Object[]), vous pouvez vraiment placer l'ensemble des éléments qui vous passent par la tête.

 

Choix du chapitre Les boîtes de confirmation

Java permet d'afficher des boîtes dites "de confirmation" offrant à l'utilisateur un choix de type Oui/Non. Il suffit pour cela de recourir à l'une des variantes de la méthode statique showConfirmDialog() de la classe JOptionPane :

  1. static int showConfirmDialog(Component composantParent, Object message) : Affiche automatiquement une boîte de dialogue de type confirmation, dont le titre est intitulé "Sélectionnez une option ", avec une icône de type question et avec l'ensemble des boutons Oui/Non/Annuler. Vous spécifiez éventuellement en argument la fenêtre parente et surtout le contenu de votre message (qui peut être de nature différente). Cette méthode retourne une valeur entière qui correspond au choix qui est fait, c'est-à-dire sur quel bouton vous avez cliqué (bouton de clôture compris).
  2. static int showConfirmDialog(Component composantParent, Object message, String titre, int typeOption) : Même boîte de confirmation que précédemment, mais cette fois-ci, vous pouvez choisir votre titre et les boutons qui vont constituer votre choix.
  3. static int showConfirmDialog(Component composantParent, Object message, String titre, int typeOption, int typeMessage) : Même boîte de confirmation que précédemment, mais cette fois-ci, vous pouvez choisir votre type de message qui se traduit par unes des icônes standard.
  4. static int showConfirmDialog(Component composantParent, Object message, String titre, int typeOption, int typeMessage, Icon icône) : Par rapport à la précédente, vous pouvez placer en plus une icône personnalisée.
Les méthodes showConfirmDialog() ressemblent beaucoup aux méthodes showMessageDialog(), si ce n'est qu'elles demandent à l'utilisateur de faire son choix et qu'elles fournissent plusieurs boutons poussoirs représentant les options disponibles. Par exemple, showConfirmDialog() peut être utilisée pour afficher un dialogue demandant "Voulez-vous vraiment quitter ?", en permettant à l'utilisateur de répondre en poussant soit un bouton Oui soit un bouton Non.

Les arguments composantParent, message, titre, typeMessage et icône de ces méthodes sont les mêmes que pour les dialogues de message. Les dialogues de confirmation ajoutent un argument typeOption et une valeur de retour.

L'argument typeOption indique quel bouton doit apparaître dans le dialogue et vous permet de choisir parmi les quatres constantes suivantes :

Comme les boîtes de message, les dialogues de confirmation sont modaux et les méthodes statiques qui les affichent bloquent jusqu'à ce que l'utilisateur ferme le dialogue. Comme les dialogues de confirmation présente des choix à l'utilisateur, ils donnent une valeur de retour reflétant le choix de l'utilisateur. Cette valeur est l'une des constantes suivantes :

Cette dernière valeur indique que l'utilisateur a fermé la fenêtre de dialogue sans sélectionner l'un des boutons disponibles ; elle doit généralement être traitée comme une réponse CANCEL_OPTION.

Confirmation pour quitter un programme

A titre d'exemple, je vous propose de prendre la première méthode showConfirmDialog() qui sera dans la plupart des cas largement suffisante. Par ailleurs, très souvent, avant de quitter une application, il est souhaitable de prévenir l'utilisateur pour que ce dernier confirme la sortie du programme, surtout si il doit penser à enregistrer ses dernières modifications effectuées dans un document.


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Dialogue extends JFrame {   
  public Dialogue() {
    super("Dialogue...");      
    getContentPane().setBackground(Color.ORANGE);
    setSize(300, 200);
    addWindowListener(new WindowAdapter() {
      @Override
         public void windowClosing(WindowEvent e) {
           if (JOptionPane.showConfirmDialog(Dialogue.this, "Désirez-vous quitter l'application ?")
              == JOptionPane.YES_OPTION) System.exit(0); 
         }
      });
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    setVisible(true);
  }
   
  public static void main(String[] args) { new Dialogue(); }
}
Là encore, le premier paramètre de la méthode statique showConfirmDialog() peut prendre la valeur null, auquel cas la boîte est affichée indépendamment d'une quelconque fenêtre.

La boîte reste affichée jusqu'à ce que l'utilisateur agisse sur l'un des boutons ou qu'il ferme la boîte. La valeur de retour de la méthode showConfirmDialog() précise l'action effectuée par l'utilisateur, sous forme d'un entier ayant comme valeur l'une des constantes suivantes de la classe JOptionPane :

  1. valeur entière 0 : YES_OPTION.
  2. valeur entière 1 : NO_OPTION.
  3. valeur entière 2 : CANCEL_OPTION.
  4. valeur entière -1 : CLOSED_OPTION.

Notez que les constantes CANCEL_OPTION et CLOSED_OPTION sont différentes. En pratique, nous exploitons rarement cette particularité. Généralement, nous considérons que dans les deux cas, nous avons affaire à un abandon du dialogue.

Imposer à l'utilisateur de faire son choix

La boîte de confirmation usuelle que nous venons de présenter permet seulement le choix de la question posée à l'utilisateur. Il existe une autre variante de la méthode showConfirmDialog() qui permet en outre de choisir le titre de la boîte, ainsi que la nature des boutons qui s'y trouvent. Ceux-ci sont définis par un paramètre entier dont la valeur est choisie parmi les constantes suivantes :

Il existe deux autres versions de la méthode statique showConfirmDialog() qui permettentde choisir en plus l'une des icônes standard où même une icône personnalisée.

A titre d'exemple, je vous propose de mettre en place une boîte de confirmation avec les seuls boutons Oui et Non. Le choix doit se faire impérativement sur l'un de ces deux boutons. Si l'utilisateur clique sur le bouton de fermeture de la boîte de confirmation, une nouvelle boîte de confirmation apparaît avec une alerte en rouge et une icône d'erreur. Tant que l'utilisateur ne choisi pas l'un des deux boutons prévues pour le choix, cette boîte de confirmation réapparaît constamment.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Dialogue extends JFrame {   
  public Dialogue() {
    super("Dialogue...");      
    getContentPane().setBackground(Color.ORANGE);
    setSize(300, 200);
    addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        switch (JOptionPane.showConfirmDialog(Dialogue.this, 
          "Désirez-vous quitter l'application ?","Sortir du programme", 
          JOptionPane.YES_NO_OPTION)) {
              
           case JOptionPane.YES_OPTION : System.exit(0); 
               
           case JOptionPane.CLOSED_OPTION : {
               JLabel alerte = new JLabel("Attention, vous devez faire un choix !");
               alerte.setForeground(Color.RED);
               int choix;
               while ((choix = JOptionPane.showConfirmDialog(Dialogue.this, 
                  new Object[] {alerte, "Désirez-vous quitter l'application ?"},
                  "Sortir du programme", 
                  JOptionPane.YES_NO_OPTION,
                  JOptionPane.ERROR_MESSAGE))==JOptionPane.CLOSED_OPTION); 
               if (choix==JOptionPane.YES_OPTION) System.exit(0);
            }
        }
      }
    });
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    setVisible(true);
  }
   
  public static void main(String[] args) { new Dialogue(); }
}
  

Réaliser une saisie à partir d'une boîte de confirmation

Bien que cela ne soit pas prévu à priori, il est tout à fait possible de prendre n'importe quel composant pour constituer notre message, et pourquoi pas un composant spécialisé dans la saisie comme un JFormattedTextField.

Bien sûr, dans le chapitre suivant nous ferrons appel à la méthode showInputDialog() de la classe JOptionPane qui est justement prévue pour la saisie, mais c'est encore une fois pour montrer la grande souplesse d'utilisation de ces méthodes statiques, notamment dans le choix du type de message.

A titre d'exemple, je vous propose donc de construire une boîte de confirmation qui permet de récupérer une valeur saisie en €uro. Cette valeur est automatiquement formatée dans la valeur monétaire européenne.

Si l'utilisateur clique sur Annuler le programme s'arrête alors sans effectuer de calcul. Par contre, si l'utilisateur clique sur le bouton OK, un traitement est réalisé et la conversion en franc est alors proposée dans une boîte de message adaptée.

L'utilisateur peut effectuer autant de calculs qu'il le désire jusqu'à ce qu'il clique sur le bouton Annuler de la boîte de confirmation.

import java.awt.Color;
import java.text.*;
import javax.swing.*;

public class Dialogue {      
  public static void main(String[] args) { 
    JFormattedTextField saisie = new JFormattedTextField(NumberFormat.getCurrencyInstance());
    saisie.setValue(0);
    Object[] message = {"Votre valeur en €uro :", saisie};
    while (JOptionPane.showConfirmDialog(null, message, "Conversion € => F", JOptionPane.OK_CANCEL_OPTION)
      == JOptionPane.YES_OPTION) {
       double €uro = ((Number)saisie.getValue()).doubleValue();
       final double CONVERSION = 6.55957;
       JFormattedTextField franc = new JFormattedTextField(new DecimalFormat("#,##0.00 F"));
       franc.setEditable(false);
       franc.setForeground(Color.RED);
       franc.setValue(€uro*CONVERSION);
       String motif = "{0, number, currency}uro{0, choice, 0#|2#s} {0, choice, 0#fait|2#font} en Franc{0, choice, 0#|0.31#s} :";
       Object[] résultat = {MessageFormat.format(motif, €uro), franc};
       JOptionPane.showMessageDialog(null, résultat);         
    }
  }
}

 

Choix du chapitre Les boîtes de saisie

La boîte de saisie permet à l'utilisateur de fournir une information sous la forme d'une chaîne de caractères. La méthode statique showInputDialog() de la classe JOptionPane vous permet de gérer automatiquement le dialogue avec l'utilisateur.

  1. static String showInputDialog(Object message) : Affiche automatiquement une boîte de dialogue de type entrée (saisie), dont le titre est intitulé "Entrée", avec une icône de type question et avec l'ensemble des boutons OK/Annuler. Vous spécifiez le contenu de votre message (qui peut être de nature différente). Cette méthode attend la saisie d'une valeur correspondant à une chaîne de caractères et retourne cette valeur dans le cas où vous avez sélectionné le bouton OK. Dans le cas contraire, c'est la valeur null qui est renvoyée.
  2. static String showInputDialog(Object message, Object valeurInitiale) : Même boîte de saisie, en proposant en plus une valeur par défaut.
  3. static String showInputDialog(Component composantParent, Object message) :
    static String showInputDialog(Component composantParent, Object message, Object valeurInitiale) : Mêmes boîtes de saisie que les précédentes, mais cette fois-ci vous spécifiez la fenêtre propriétaire.
  4. static String showInputDialog(Component composantParent, Object message, String titre, int typeMessage) : Même boîte de saisie que précédemment, mais cette fois-ci, vous pouvez choisir votre titre ainsi que l'icône prédéfinie.
  5. static Object showInputDialog(Component composantParent, Object message, String titre, int typeMessage, Icon icône, Object[] valeursSélection, Object valeurInitiale) : Il s'agit en réalité ici plutôt d'une boîte de sélection qu'une boîte de saisie. En effet, vous proposez à l'argument valeursSélection le tableau de valeurs possibles qui sera généralement représenté par une boîte combo.
Les méthodes showInputDialog() de la classe JOptionPane représentent les dialogues d'entrée. La plupart des versions de ces méthodes prennent les mêmes arguments que les dialogues de message. Cependant, en plus d'afficher un message, ils contiennet également un JTextField dans lequel l'utilisateur peut entrer la valeur demandée.

Ces dialogues sont modaux et les méthodes qui les affichent bloquent jusqu'à ce que l'utilisateur ferme le dialogue.
La dernière version de showInputDialog() prend l'argument supplémentaire valeursSélection. Ainsi, au lieu de demander à l'utilisateur de rentrer une chaîne, elle le fait choisir parmi les valeurs contenues dans le tableau valeursSélection. L'affichage de ces valeurs est laissé au look-and-feel courant, bien qu'elles soient habituellement affichées par un composant JComboBox ou JList. Le tableau valeursSélection contient généralement des chaînes de caractères, mais il peut aussi contenir des objets Icon ou d'autres qui peuvent être affichées de manière significative par les composants JList et JComboBox.

Quand nous passons un tableau de valeursSélection à showInputDialog(), la valeur de retour est celle que l'utilisateur aura choisi, ou null si l'utilisateur n'a pas sélectionné le bouton OK.

Mise en oeuvre d'une boîte de saisie

Comme d'habitude, je vous propose de mettre en place une boîte de saisie la plus simple possible. Effectivement, nous allons utiliser la méthode showInputDialog() qui possède comme seul argument le message désiré, ici "Nom du fichier :". Nous construisons une application qui permet de consulter un document enregistré dans un fichier. Dès que le programme débute, la boîte de saisie apparaît en nous demandant d'introduire le nom du fichier désiré. Si ce nom est correct, une fenêtre est alors créée et nous montre le document concerné. Dans le cas contraire, une boîte de message est alors proposée nous indiquant notre erreur de saisie à l'issu de quoi, le programme s'arrête.

codage correspondant
import java.awt.Color;
import java.io.*;
import javax.swing.*;

public class Dialogue {      
  public static void main(String[] args) { 
    String nomFichier = JOptionPane.showInputDialog("Nom du fichier :");
    try {
      JTextArea document = new JTextArea();
      document.setBackground(Color.ORANGE);
      document.read(new FileReader(nomFichier), null);
      JFrame fenetre = new JFrame(nomFichier);
      fenetre.add(new JScrollPane(document));
      fenetre.setDefaultCloseOperation(fenetre.EXIT_ON_CLOSE);
      fenetre.setSize(400, 300);
      fenetre.setVisible(true);
    } 
    catch (IOException ex) {
      JOptionPane.showMessageDialog(null, 
        "ATTENTION, le fichier ("+nomFichier+") n'existe pas", 
        "Alerte", 
        JOptionPane.ERROR_MESSAGE);
    }
  }
}

Boîte de sélection

Nous remarquons que c'est vraiment très facile de construire une boîte de saisie. Il existe bien entendu plein de variantes dont nous connaissons bien les principes maintenant, et je ne vais d'ailleurs pas m'y attarder. Je vous propose toutefois de travailler avec la dernière méthode showInputDialog() puisqu'elle est un peu plus particulière dans le sens où il est possible de proposer un choix parmi un ensemble de valeurs prédéfinies.

A titre d'exemple, voici une boîte de sélection qui permet de choisir l'affichage entre la date et/ou l'heure actuelles :

codage correspondant
import java.text.*;
import java.util.Date;
import javax.swing.*;

public class Dialogue {      
  public static void main(String[] args) { 
    DateFormat date = DateFormat.getDateInstance(DateFormat.FULL);
    SimpleDateFormat heure = new SimpleDateFormat("HH 'h' mm 'mn'");
    String[] sélections = {"Date", "Heure", "Date et heure"};
    String choix = (String)JOptionPane.showInputDialog(null,
       "Faites votre choix ?", 
       "Date et heure",  
       JOptionPane.QUESTION_MESSAGE, 
       null,
       sélections, 
       null);
    if (choix.equals("Date")) {
       String message = date.format(new Date());
       JOptionPane.showMessageDialog(null, message, choix, JOptionPane.INFORMATION_MESSAGE);
    }
    else if (choix.equals("Heure")) {
       String message = heure.format(new Date());
       JOptionPane.showMessageDialog(null, message, choix, JOptionPane.INFORMATION_MESSAGE);       
    }
    else {
       String[] message = {date.format(new Date()), heure.format(new Date())};
       JOptionPane.showMessageDialog(null, message, choix, JOptionPane.INFORMATION_MESSAGE); 
    }
  }
}
  

Choix du chapitre Les boîtes d'options

Il existe une dernière boîte de dialogue prédéfinie qui s'appelle tout simplement boîte d'options. Cette boîte d'options, représentée par la méthode statique showOptionDialog(), généralise en fait la boîte de dialogue de confirmation. Il existe effectivement un argument supplémentaire, appelé options, qui indique quels boutons afficher dans la boîte de dialogue. Ils remplacent alors les boutons traditionnels, comme OK/Annuler. Vous pouvez ainsi proposer des libellés qui correspondent plus précisément à votre application.

static Object showOptionDialog(Component composantParent, Object message, String titre, int typeOption, int typeMessage, Icon icône, Object[] options, Object valeurInitiale) : Boîte de dialogue de type option. Il existe une seule méthode. Du coup, vous devez spécifier un nombre considérable d'arguments. Nous connaissons déjà au travers des autres méthodes le rôle de chacun de ces arguments. Celui qui est le plus important ici, et c'est ce qui fait sa spécificité, c'est l'argument options au travers duquel vous passez l'ensemble des éléments qui constituerons les boutons de la boîte de dialogue, sous forme de tableaux d'objets.

Dans cet argument options, nous spécifions typiquement un tableau de chaînes que JOptionPane affiche dans des composants JButton. Ces boutons s'affichent alors sur la même ligne. Rien n'empêche toutefois de choisir d'autres types de composants, comme des zones de saisie, des libellés, etc.

La valeur de retour est, comme pour la boîte de confirmation, de type entier. Le nombre retourné correpond à l'ordre de placement des boutons en commençant par 0. Ainsi, si vous cliquez sur le troisième bouton, c'est le chiffre 2 qui est renvoyée par la boîte de dialogue.

Mise en oeuvre d'une boîte d'option

A titre d'exemple, je vous propose de fabriquer une boîte de dialogue qui permet de nous connecter à un service particulier. Nous pouvons nous connecter à ce service soit de façon anonyme, c'est-à-dire tout public, ou éventuellement en mode privé auquel cas, vous devez alors donner votre nom d'utilisateur et spécifier votre mot de passe.

codage correspondant
import javax.swing.*;

public class Dialogue {
  public static void main(String[] args) {
    JTextField utilisateur = new JTextField();
    JPasswordField motDePasse = new JPasswordField();
    int choix = JOptionPane.showOptionDialog(null, 
       new Object[] {"Votre nom :", utilisateur, "Mot de passe :", motDePasse},
       "Connexion",
       JOptionPane.NO_OPTION,
       JOptionPane.QUESTION_MESSAGE, null, 
       new String[] {"Mode privé", "Anonyme", "Annuler"}, null); 
    
    switch (choix) {
       case 0 : if (utilisateur.getText().equalsIgnoreCase("Emmanuel REMY") && motDePasse.getText().equals("manu"))
                         JOptionPane.showMessageDialog(null, "Vous êtes connecté en mode privé"); 
                     else
                         JOptionPane.showMessageDialog(null, 
                             new String[] {"Utilisateur inconnu", "ou mot de passe incorrecte"},
                             "Connexion en mode privée refusée",
                             JOptionPane.ERROR_MESSAGE);
                     break;
        case 1 : JOptionPane.showMessageDialog(null, "Vous êtes connecté en mode tout public"); break;
        default : JOptionPane.showMessageDialog(null, "Non connecté...", "ATTENTION", JOptionPane.ERROR_MESSAGE); break;
    }
  }
}

Même type de connexion mais avec des boutons standards

Bien entendu, vous n'êtes pas obligé de prendre en compte l'argument options (vous proposez alors la valeur null) de cette méthode showOptionDialog(). Dans ce cas là, il vous faut préciser les boutons standards que vous désirez voir apparaître au travers de l'argument typeOption.

codage correspondant
import javax.swing.*;

public class Dialogue {
  public static void main(String[] args) {
    JTextField utilisateur = new JTextField();
    JPasswordField motDePasse = new JPasswordField();
    int choix = JOptionPane.showOptionDialog(null, 
      new Object[] {"Votre nom :", utilisateur, "Mot de passe :", motDePasse},
      "Connexion",
      JOptionPane.OK_CANCEL_OPTION,
      JOptionPane.QUESTION_MESSAGE, null,  null, null); 
    
    if (choix == JOptionPane.OK_OPTION) 
      if (utilisateur.getText().equalsIgnoreCase("Emmanuel REMY") && motDePasse.getText().equals("manu"))
         JOptionPane.showMessageDialog(null, "Vous êtes connecté"); 
      else
         JOptionPane.showMessageDialog(null, 
           new String[] {"Utilisateur inconnu", "ou mot de passe incorrecte"},
           "Connexion refusée",
           JOptionPane.ERROR_MESSAGE);
    else
      JOptionPane.showMessageDialog(null, "Non connecté...", "ATTENTION", JOptionPane.ERROR_MESSAGE);    
  }
}

Prendre à la place une boîte de confirmation avec la méthode showConfirmDialog()

La particularité de la boîte d'options par rapport à la boîte de confirmation c'est uniquement le nombre de boutons que vous désirez placer dans la boîte de dialogue et le choix de leurs libellés. Si vous ne désirez pas créer de nouveaux boutons et si vous préférez plutôt utiliser les boutons standards, autant choisir une boîte de dialogue de type confirmation, dont la méthode showConfirmDialog() possède moins d'arguments à prendre en compte.

</