1 

Multithreading en SWING

Introduction

"Swing" est un kit de composants inclut depuis 1996 dans la version 1.1 du Java Development Kit (JDK). Les composants Swing fournissaient et continuent à fournir une bonne alternative aux composants Abstract Window Toolkit (AWT). Les composants AWT sont utilisés pour le développement d'interface graphique utilisateurs, on parle encore IHM (Interface Homme Machine).

Les composants Swing font partie des Java Foundation Classes (JFC), ils utilisent donc directement la technologie de base de Java.

Pré-requis

Dans la plupart des tutoriaux que l'on peut trouver sur les composants Swing, ceux-ci sont décrits comme étant de simples thread. Tous les accès à un composant réalisé doivent être envoyés à l'aide d'un thread d'événements. Le terme de composant réalisé est associé le plus souvent aux composants graphiques affichés à l'écran.

En pratique, cela signifie qu'avant de montrer un composant Swing à l'écran, vous devez construire une fenêtre en définissant toutes les propriétés nécessaires.

Ceci est démontré dans le programme suivant, Swing1, qui ajoute d'abord des boutons à une fenêtre puis qui l'affiche :

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

public class Swing1 {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setTitle("Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton();
button.setText("Hello, World!");
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.setSize(200, 100);
frame.show();
}
}

En regardant ce programme simpliste, vous devriez présumer qu'il n'y a aucune erreur avec celui-ci. D'autres programmes similaires sont dans chaque tutorial et article sur les composants Swing, incluant ceux de Core Java Technologies Tech Tips. En fait, il y a bien une erreur dans ce programme.

Explication

Le problème ici est l'affichage des méthodes appelées. Plus précisément, la source d'erreur est l'appel sous-jacent à la méthode setVisible(true) qui déclenche un appel au jeu de conteneurs. Les deux appels aux méthodes setVisible et celles du jeu de conteneurs créeront une paire d'associations pour la fenêtre. Avec la création d'une paire, le systême crée un évènement envoyant des threads. Cela pose une problématique car l'événement envoyant un thread doit être notifié dans les écouteurs quand le package et la validation seront encore en processus. Cette situation devrait se résoudre en deux threads dialoguant avec les composants Swing de base (GUI). C'est un flux sérieux qui conduira à une impasse ou d'autres issues définies grâce aux threads. Un package appelle des composants afin qu'ils soient réalisés. S'ils doivent être réalisés (ce qui n'est pas nécessairement visible), ils pourront déclencher des notifications d'écoute sur l'envoi d'évènements grâce aux threads.

Comment résoudre ce problême? Simplement ne pas montrer une fenêtre dans la méthode main().Vous pouvez toujours écrire tout le code de création GUI dans la méhode main(). Cependant, quand il faudra rendre visible la fenêtre, faites le à partir de l'événement d'envoi de threads. Cela assurera que, en plus, seulement un thread pourra initialiser le composant Swing.

Ici, l'exemple original du programme a été revu afin d'être sans danger aux threads.

import javax.swing.* ;
import java.awt.* ;
import java.lang.reflect.* ;

public class Swing2 {
private static class FrameShower implements Runnable {
final Frame frame;
public FrameShower(Frame frame) {
this.frame = frame;
}
public void run() {
frame.show();
}
}

public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setTitle("Title");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
JButton button = new JButton();
button.setText("Hello, World!");
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.setSize(200, 100);
Runnable runner = new FrameShower(frame);
EventQueue.invokeLater(runner);
}
}

Comparons avec le programme original, les seuls changements sont au niveau de la création d'une classe Runnable : 

private static class FrameShower implements Runnable {
final Frame frame;
public FrameShower(Frame frame) {
this.frame = frame;
}
public void run() {
frame.show();
}
}
...
Runnable runner = new FrameShower(frame);

Et ensuite passons cet objet Runnable à la méthode invokeLater (ou invokeAndWait ) :

EventQueue.invokeLater(runner);

Appelée correctement, le résultat est une version d'un exemple de programme vraiment sans danger pour les threads. Vous devriez examiner vos programmes et les mettre à jour si l'utilisation des threads en Swing est faite de manière inapropriée.

Voir le cours complet sur Swing.
Voir le cours complet sur les Threads.


1 

Retrouvez ci-dessous les autres sections du Laboratoire Sun
Evènements
Java Sun Net Talk LIVE CHAT le 2 Avril à 16h303/29/08
SolarisSunDécouvrez les nouveaux Sun Fire sous Intel10/11/07
JavaValtech Days10/9/07
JavaApacheCon du 1 au 4 mai à Amsterdam2/13/07

Exemples de code
JavaManipuler les looks and feel (lister et affecter)10/15/07
JavaFaire sa propre injection de dépendance avec les annotations5/9/06
JavaSplash screen avec progress Bar5/5/06
JavaFaire un splash screen en swing5/5/06

Actualités
SunProjet Kenai: une nouvelle forge open source10/3/08
SunSun Microsystems en forme !8/4/08
SunOpenDS un ldap 100% java7/24/08
SunSun et Fujitsu annoncent un nouveau Sparc647/16/08
SunVisualVM, un outil de surveillance des applications Java7/10/08

Tips du laboratoire
EclipseVisual Editor avec Eclipse Europa, c'est possible3/28/08
EclipseGérer les projets dans un workspace.10/16/07
JavaManager votre server d'application avec Eclipse4/21/07
JavaVue des sub-packages avec Eclipse4/21/07
JavaGlisser-déposer avec Eclipse4/21/07

Laboratoire SUPINFO des technologies Sun
labo-sun@supinfo.com


Conditions d'utilisation et © Copyright SUPINFO International University
23, rue de Château Landon - 75010 PARIS - Tél : +33 (0) 153359700 Fax : +33 (0) 153359701
Respect de la vie privée