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.
|