Interfaces graphiques avec Swing

Introduction

Swing et Java SE

Une librairie historique…

La librairie Swing est aujourd’hui largement utilisée dans de nombreuses applications Java.

JavaFX est une librairie de substitution mise en avant par Oracle et présentée comme devant être privilégiée par rapport à Swing.

… partie intégrante de la spécification Java SE

Cependant, comme indiqué sur cette page, Swing est et restera une partie de la spécification Java SE.

Swing fait donc partie du JRE et le restera.

Hello World

Le programme Hello World en Swing peut se faire de la manière suivante :

package com.example.swing;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class HelloSwing implements Runnable {
    public void run(){
        //Initialise la fenêtre
        JFrame frame = new JFrame("Hello Swing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        //Ajoute un label
        JLabel label = new JLabel("Hello World !!!");
        frame.getContentPane().add(label);
        
        //Positionne et redimensionne la fenêtre
        frame.setBounds(200, 200, 300, 240);
        frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new HelloSwing());
    }
}

Étapes principales:

Instructions particulières

Fermeture de la fenêtre

L’instruction suivante permet de terminer le programme dès que la fenêtre est fermée:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Ajout d’un composant

L’ajout d’un composant se fait en utilisant la méthode add(JComponent)

frame.getContentPane().add(label);

Affichage de la fenêtre

Ajouter l’instruction suivante juste avant la ligne frame.setVisible(true) :

frame.setVisible(true);

Dimensionnement automatique de la fenêtre

Ajouter l’instruction suivante juste avant la ligne frame.setVisible(true) :

frame.pack();

Le lancement Thread-safe

Comme indiqué sur cette page il est nécessaire de lancer l’interface ainsi:

SwingUtilities.invokeLater(new HelloSwing());

Ceci est dû à la manière de gérer les événements et permet d’éviter des exceptions ou bugs lors de l’affichage du programme.

Les composants

Le paquet AWT

AWT = Abstract Window Toolkit

Ce paquet fait partie intégrante de l’API Java.

Il inclut des composants utilisables sur tous les environnements graphiques.

Classes AWT
Classes AWT

AWT + Swing

Les composants Swing sont basés sur l’API AWT et les complètent avec des fonctionnalités supplémentaires.

Classes AWT
Classes AWT

Composants Swing

Ces composants sont indépendants des environnements graphiques.

Composants Swing
Composants Swing

Composants Swing basiques

JPanel et JLabel sont les composants les plus basiques:

Composants Swing
Composants Swing

Composants Swing : boutons

Les boutons permettent d’interagir avec la souris sur les interfaces

Composants Swing
Composants Swing

Composants Swing : texte

Les zones de texte permettent d’afficher/éditer du texte

Composants Swing
Composants Swing

Disposition des éléments

Layout : agencement et disposition

Agencer les composants = assurer une cohérence visuelle

Layout = Gestionnaire d’agencement

L’architecte d’intérieur de l’interface graphique

Composition d’IHM

Exercices

JButton et JLabel

Créer une fenêtre contenant:

Dimensionner la fenêtre pour que les éléments soient disposés sur une seule ligne

JButton et JLabel

Créer une fenêtre contenant:

Faites en sorte que la dimension de la fenêtre

JButton et JLabel

Créer une fenêtre contenant:

Changer d’apparence

Le Look And Feel

Le Look And Feel est une couche spécifique pour modifier l’affichage et le comportement des composants graphiques.

Il peut être modifié au démarrage ou en cours d’exécution.

Expérimentation du Look And Feel

Créer la classe SwingExample.java :

package com.example.swing;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SwingExample {
    private JFrame frame ;
    private JLabel label ;
    void init(){
        //Initialise la fenêtre
        frame = new JFrame("Swing Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        //Ajoute un label
        label = new JLabel("About to change Look and Feel");
        frame.getContentPane().add(label, BorderLayout.NORTH);
        
        JButton button = new JButton("Does nothing");
        frame.getContentPane().add(button, BorderLayout.SOUTH);
        
        //Positionne et redimensionne la fenêtre
        frame.setBounds(200, 200, 300, 240);
        frame.setVisible(true);
    }
    
    public void setLookAndFeel(String name, String className){
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                try {
                    UIManager.setLookAndFeel(className);
                    label.setText(name);
                    SwingUtilities.updateComponentTreeUI(frame);
                    frame.pack();
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                        | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }
            }
        });
        
    }
}

Modification en cours d’exécution

Créer et exécuter la classe exécutable LookAndFeel.java :

package com.example.swing;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class LookAndFeel {
    public static void main(String[] args) {        
        SwingExample example = new SwingExample();
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){ example.init(); }
        });
        
        LookAndFeelInfo[] lafiArray = UIManager.getInstalledLookAndFeels();
        int i = 0;
        while(true){
            if(i >= lafiArray.length){
                i = 0;
            }
            LookAndFeelInfo lafi = lafiArray[i];
            System.out.println(lafi.getName()+" : "+lafi.getClassName());
            try {
                Thread.sleep(2000);

                example.setLookAndFeel(lafi.getName(), lafi.getClassName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
    }
}

Modification au démarrage

Créer une nouvelle classe nommée FixedLookAndFeel.

Dans la méthode main, utiliser la méthode suivante avec un Look And Feel de votre choix :

UIManager.setLookAndFeel(String className);

Afficher la fenêtre de SwingExample.

L’architecture des Swing

L’architecture MVC

Modèle-Vue-Contrôleur

MVC
MVC

Intérêt de MVC

MVC
MVC

Swing est (presque) MVC

Il a été difficile d’appliquer MVC à l’architecture Swing, cependant, celle-ci s’en inspire.

MVC
MVC