Semaine 9

Activité 2

Revue de la bibliothèque de codes Java Swing

Sommaire

Le langage Java  intègre, depuis sa version 1.2, l’API Swing, un ensemble de classes permettant la création de composantes graphiques. Ces classes proposent des fonctionnalités plus sophistiquées que les plus anciennes classes de l’API  Abstract Window Toolkit (AWT) de Java. Par exemple, elles intègrent de façon native (bref, dans le code natif du système d’exploitation de la machine virtuelle Java) le Look and Feel de celui-ci. Le Look and Feel est le standard graphique qu’un système d’exploitation donne à ses composantes graphiques : fenêtres, boîtes de dialogue, boutons, etc.

 lookAndFeel

 Look and Feel de Windows vs Mac OS X

JFrame

L’objet de base Swing permettant de créer une fenêtre d’application se nomme JFrame. Il s’agit de la composante graphique correspondant à la fenêtre d’application standard avec boutons aux coins supérieurs (selon le Look and Feel) permettant de réduire ou de fermer la fenêtre. À ce JFrame, il est possible d’apposer des menus (JMenu) et les autres composantes graphiques Swing. Voici un exemple de JFrame.

 

public class ExempleDeJFrame extends javax.swing.JFrame {

    /**
     * Constructeur
     */
    public ExempleDeJFrame() {
       // Appelle une méthode d’initialisation tel que formaté dans l’IDE NetBeans
        initComponents();
    }

    /**
     * Initialise les composantes
     */
    private void initComponents() {

        // Permet de fermer le JFrame lorsque le bouton standard (coin supérieur) est appuyé
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        // Méthode de l’objet JFrame permettant d’ajuster la taille du JFrame selon les tailles des composantes Swing incluses dans le Frame. Exemple, que la taille du Frame soit supérieure ou égale à la taille d’un bouton inclus dans le frame. 
       pack();
    } 

    /**
     *@param args the command line arguments
     */
    public static void main(String args[]) {
    // Exemple d’utilisation d’un Look And Feel, dans ce cas-ci Nimbus
    try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        // Créé un Thread (fil d’exécution) intégrant l’instanciation du JFrame
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ExempleDeJFrame().setVisible(true);
            }
        });
    }
}

JPanel

L’organisation des composantes à l’intérieur d’un JFrame se fait en utilisant les JPanel et la combinaison de différents layouts (mises en page). Un JPanel est une composante Swing, apparentée à un tableau d’affichage, permettant d’afficher d’autres composantes graphiques Swing selon certaines dispositions gérées  par un Layout. La stratégie générale de construction d’une interface avec Swing est de créer une structure de plusieurs JPanel imbriqués (un JPanel peut contenir d’autres JPanel) ayant différents layouts afin d’arriver aux résultats souhaités.

Un JPanel peut être formaté pour afficher des bordures (borders), un fond de couleur spécifique, etc. Également, un JFrame comprend par défaut un premier JPanel. Voici un exemple de JFrame intégrant un JPanel avec une bordure de type TitleBorder.

JPanelAvecBorder

 Code associé à ce JPanel :

public class ExempleDeJFrame extends javax.swing.JFrame {

    public ExempleDeJFrame() {
        initComponents();
    }

    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        // Spécification du type de bordure
        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Exemple de JPanel"));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 388, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 276, Short.MAX_VALUE)
        );

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        pack();
    }

    /**
     *@param args the command line arguments
     */
    public static void main(String args[]) {

    try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ExempleDeJFrame().setVisible(true);
            }
        });
    }

	private javax.swing.JPanel jPanel1;
}

 

Il existe également un ensemble d’autres composantes de type « conteneur » (container) dans l’API Swing, dont :

Layout (mise en page)

Comme il est indiqué précédemment, les objets « conteneurs » de Swing tels que le JPanel peuvent être formatés pour gérer automatiquement la disposition des composantes graphiques qu’ils présentent. Certains modèles de mise en page tels que le Absolute Layout permettent de placer des composantes graphiques selon des dispositions précises, mais l’avantage premier de l’utilisation de ces modèles est l’automatisation de la disposition des composantes selon un schéma propre aux modèles utilisés. Les layouts permettent également d’automatiser la disposition des composantes selon la manipulation de la taille des JFrame et JPanel. Par  exemple, avec le FlowLayout et la réduction par l’utilisateur de la taille du JFrame, les emplacements des boutons sont automatiquement  ajustés dans le JFrame selon la taille disponible :

 exempleFlowLayout

 

Code associé à cette figure : 
public class ExempleDeJFrame extends javax.swing.JFrame {

    /**
     * Creates new form ExempleDeJFrame
     */
    public ExempleDeJFrame() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.FlowLayout());

        jButton1.setText("jButton1");
        getContentPane().add(jButton1);

        jButton2.setText("jButton2");
        getContentPane().add(jButton2);

        jButton3.setText("jButton3");
        getContentPane().add(jButton3);

        jButton4.setText("jButton4");
        getContentPane().add(jButton4);

        pack();
    }

    /**
     *@param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see https://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ExempleDeJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ExempleDeJFrame().setVisible(true);
            }
        });
    }

    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;

}

Chaque sous-classe de JLayout a son utilité et gère de façon différente la disposition des composantes graphiques. Voici un résumé des modèles de mise en page les plus utilisés. Vous pouvez également consulter le document officiel (en anglais) sur le site  Java/Oracle (https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) :

Type de modèles de mise en page

Description

AbsoluteLayout

Il s’agit en fait du modèle de mise en page par défaut lorsque celui-ci n’est pas spécifié (p. ex., *.setLayout(null)).

 

Place les objets selon des références en x et y selon le point de référence (0,0) correspondant au coin supérieur droit du JFrame.

 

Documentation officielle (en anglais) : https://docs.oracle.com/javase/tutorial/uiswing/layout/none.html

BorderLayout

Place les objets selon 5 zones prédéfinies : nord, sud, est, ouest et centre.

borderLayout

Très pratique pour construire un formulaire dans la zone centrale et des boutons dans la zone sud :

Ici, la zone centrale est un JPanel ayant une bordure titrée « Formulaire » et la zone sud est un JPanel avec 2 boutons.

 

Documentation officielle (en anglais) :

https://docs.oracle.com/javase/tutorial/uiswing/layout/border.html

 

FlowLayout

Il s’agit du modèle de mise en page par défaut de tous les JPanel. Il place les objets sur une même ligne (quand l’espace le permet) depuis la gauche vers la droite. Il gère automatiquement l’espace entre les composantes, selon l’espace total disponible.

 flowLayout

Documentation officielle (en anglais) :

https://docs.oracle.com/javase/tutorial/uiswing/layout/flow.html

 

GridLayout

Permet la disposition des composantes de même taille selon une grille comportant des lignes et des colonnes.

 gridlayout

Documentation officielle (en anglais) :

https://docs.oracle.com/javase/tutorial/uiswing/layout/grid.html

 

BoxLayout

Modèle de mise en page qui permet de mettre les composantes sur une seule ligne ou colonne.

 boxLayout

 

Documentation officielle (en anglais) :

https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html

 

GridBagLayout

Il s’agit d’un modèle de mise en page permettant de placer des composantes dans un JPanel selon une grille, où les composantes peuvent prendre plus qu’une cellule de la grille. Il est également possible de modifier la hauteur ou largeur de colonnes ou de lignes précises à l’aide du LayoutManager.

GridBagLayout

Documentation officielle (en anglais) :

https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html

 

 

Voici une vidéo de type tutoriel présentant l’usage de ces modèle de mise en page et le code produit.

 

Autres composantes graphiques de Swing

Il existe des composantes Swing équivalentes pour chacun des composantes AWT avec des constructeurs semblables.  Voici les principales composantes graphiques  de l’API Swing :

Nom de la classe

Description

JLabel

Il s’agit d’un champ de texte non éditable permettant d’afficher du texte dans une interface graphique.

JButton

Il s’agit de la  composante graphique classique représentant un bouton poussoir.

JToggleButton

Bouton poussoir ayant un état de type ouvert/fermé.

JCheckBox

Composante graphique représentant la case à cocher classique.

JRadioButton

Autre type de case à cocher permettant un choix unique parmi un groupe de JRadioButton. Cette composante est généralement utilisée avec l’objet JButtonGroup (voir ci-dessous).

ButtonGroup

Objet permettant de contrôler l’utilisation d’un groupe de JRadioButton ou d’autres types de boutons (p. ex., JToggleButton).

JTextField

Composante graphique permettant à l’utilisateur une entrée textuelle sous la forme d’une seule ligne de texte.

JTextArea

Composante graphique permettant à l’utilisateur une entrée textuelle sous la forme de plusieurs lignes de texte.

JList

Composante graphique permettant à l’utilisateur de sélectionner un ensemble d’entrées dans une liste de champs textuels.

JComboBox

Composante graphique offrant une liste déroulante lorsque l’utilisateur sélectionne la composante.

JTable

Composante graphique permettant d’afficher un tableau de données qui peuvent être éditables ou ne pas l’être. La gestion du contenu de la table se fait par l’entremise de la création d’une sous-classe de l’objet TableModel.

 

Un exemple d’utilisation des JTable est présenté dans la vidéo suivante. Voici la documentation officielle d’Oracle : https://docs.oracle.com/javase/tutorial/uiswing/components/table.html

JTree

Composante graphique permettant d’afficher une arborescence d’éléments (p. ex., un système de fichier). Fonctionne de pair avec une structure de données arborescentes avec l’objet DefaultMutableTreeNode.

 

Exemple d’utilisation de JTree avec la documentation officielle d’Oracle : https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html

 

Voici une vidéo de type tutoriel présentant les principales composantes graphiques de Swing et indiquant la façon de les utiliser dans une interface graphique Java. Voici également le code produit lors de cet exercice (fichier compressé, zip contenant le code source. Il s’agit d’un projet NetBeans que vous pouvez ouvrir dans votre IDE).

 Vidéo externe sans voix :

Le code associé est accessible ici: https://koor.fr/Java/SupportSwing/slide1.wp

Il également possible d’ajouter des images de type icône à ces composantes graphiques. Pour ce faire, il suffit d’ajouter l’objet gérant l’affichage de l’icône au constructeur de la composante graphique. Le constructeur d’un objet Icon admet comme seul paramètre le nom ou l’URL d’un fichier graphique.

 

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

public class UneFenetre extends JFrame {

  public swing3() {

     super("titre de l'application");

      WindowListener l = new WindowAdapter() {
         public void windowClosing(WindowEvent e){
            System.exit(0);
         }
      };

      addWindowListener(l);

      ImageIcon img = new ImageIcon("tips.gif");
      JButton bouton = new JButton("Mon bouton",img);

      JPanel panneau = new JPanel();
      panneau.add(bouton);
      setContentPane(panneau);
      setSize(200,100);
      setVisible(true);
   }

  public static void main(String [] args){
      JFrame frame = new swing3();
  }
}

Au cours des prochaines semaines, nous apprendrons à mieux connaître ces composantes en les utilisant dans plusieurs exercices. Entre autres, nous y intégrerons de l’événementiel afin que les applications mises au point réagissent aux interactions des utilisateurs avec ces composantes graphiques.